diff --git a/LibReplanetizer/Headers/MobyloadHeader.cs b/LibReplanetizer/Headers/MobyloadHeader.cs new file mode 100644 index 0000000..f7afebe --- /dev/null +++ b/LibReplanetizer/Headers/MobyloadHeader.cs @@ -0,0 +1,66 @@ +// Copyright (C) 2018-2023, The Replanetizer Contributors. +// Replanetizer is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// Please see the LICENSE.md file for more details. + +using System; +using System.Collections.Generic; +using System.IO; +using static LibReplanetizer.DataFunctions; + +namespace LibReplanetizer.Headers +{ + public class MobyloadHeader + { + public int mobyCount; + public int textureCount; + public int texturePointer; + public int textureDataPointer; + public List> modelData = new List>(); + + public MobyloadHeader(FileStream mobyloadFile) + { + byte[] headerBytes = ReadBlock(mobyloadFile, 0x00, 0x10); + + mobyCount = ReadInt(headerBytes, 0x00); + textureCount = ReadInt(headerBytes, 0x04); + texturePointer = ReadInt(headerBytes, 0x08); + textureDataPointer = ReadInt(headerBytes, 0x0C); + + byte[] pointerBlock = ReadBlock(mobyloadFile, 0x10, mobyCount * 0x0C); + + for (int i = 0; i < mobyCount; i++) + { + int modelPointer = ReadInt(pointerBlock, 0x00 + i * 0x0C); + int modelID = ReadInt(pointerBlock, 0x04 + i * 0x0C); + + modelData.Add(new Tuple(modelPointer, modelID)); + } + } + + public static string? FindMobyloadFile(GameType game, string enginePath, int id) + { + string? folder = Path.GetDirectoryName(enginePath); + + switch (game.num) + { + case 3: + case 4: + string? path = Path.Join(folder, "mobyload" + id + ".ps3"); + if (File.Exists(path)) return path; + break; + } + + return null; + } + + public byte[] Serialize() + { + byte[] bytes = new byte[0x10]; + + return bytes; + } + } +} diff --git a/LibReplanetizer/Level.cs b/LibReplanetizer/Level.cs index 0403424..cca9d2c 100644 --- a/LibReplanetizer/Level.cs +++ b/LibReplanetizer/Level.cs @@ -60,6 +60,8 @@ public class Level public List terrainChunks; public List textureConfigMenus; public List missions; + public List> mobyloadModels; + public List> mobyloadTextures; public LevelVariables levelVariables; public OcclusionData? occlusionData; @@ -268,7 +270,7 @@ public Level(string enginePath) for (int i = 0; i < 5; i++) { - var chunkPath = Path.Join(path, @"chunk" + i + ".ps3"); + string? chunkPath = Path.Join(path, @"chunk" + i + ".ps3"); if (!File.Exists(chunkPath)) continue; using (ChunkParser chunkParser = new ChunkParser(chunkPath, game)) @@ -371,6 +373,27 @@ public Level(string enginePath) missions.Add(mission); } + mobyloadModels = new List>(); + mobyloadTextures = new List>(); + + for (int mobyloadFileID = 0; mobyloadFileID < 32; mobyloadFileID++) + { + string? mobyloadFilePath = MobyloadHeader.FindMobyloadFile(game, enginePath, mobyloadFileID); + if (mobyloadFilePath != null) + { + using (MobyloadParser parser = new MobyloadParser(game, mobyloadFilePath)) + { + mobyloadModels.Add(parser.GetMobyModels()); + mobyloadTextures.Add(parser.GetTextures()); + } + } + else + { + mobyloadModels.Add(new List()); + mobyloadTextures.Add(new List()); + } + } + using (VramParser vramParser = new VramParser(path + @"/vram.ps3")) { vramParser.GetTextures(textures); diff --git a/LibReplanetizer/LibReplanetizer.csproj b/LibReplanetizer/LibReplanetizer.csproj index 41c7976..35910af 100644 --- a/LibReplanetizer/LibReplanetizer.csproj +++ b/LibReplanetizer/LibReplanetizer.csproj @@ -6,9 +6,10 @@ - - - + + + + diff --git a/LibReplanetizer/Models/Model.cs b/LibReplanetizer/Models/Model.cs index 00ed6cd..58f49a0 100644 --- a/LibReplanetizer/Models/Model.cs +++ b/LibReplanetizer/Models/Model.cs @@ -270,15 +270,15 @@ public static float[] GetVertices(FileStream fs, int vertexPointer, int uvPointe byte[] uvBlock = ReadBlock(fs, uvPointer, vertexCount * uvElemSize); for (int i = 0; i < vertexCount; i++) { - vertexBuffer[(i * 8) + 0] = (ReadFloat(vertBlock, (i * vertexElemSize) + 0x00)); //VertexX - vertexBuffer[(i * 8) + 1] = (ReadFloat(vertBlock, (i * vertexElemSize) + 0x04)); //VertexY - vertexBuffer[(i * 8) + 2] = (ReadFloat(vertBlock, (i * vertexElemSize) + 0x08)); //VertexZ - vertexBuffer[(i * 8) + 3] = (ReadFloat(vertBlock, (i * vertexElemSize) + 0x0C)); //NormX - vertexBuffer[(i * 8) + 4] = (ReadFloat(vertBlock, (i * vertexElemSize) + 0x10)); //NormY - vertexBuffer[(i * 8) + 5] = (ReadFloat(vertBlock, (i * vertexElemSize) + 0x14)); //NormZ - - vertexBuffer[(i * 8) + 6] = (ReadFloat(uvBlock, (i * uvElemSize) + 0x00)); //UVu - vertexBuffer[(i * 8) + 7] = (ReadFloat(uvBlock, (i * uvElemSize) + 0x04)); //UVv + vertexBuffer[(i * 8) + 0] = ReadFloat(vertBlock, (i * vertexElemSize) + 0x00); //VertexX + vertexBuffer[(i * 8) + 1] = ReadFloat(vertBlock, (i * vertexElemSize) + 0x04); //VertexY + vertexBuffer[(i * 8) + 2] = ReadFloat(vertBlock, (i * vertexElemSize) + 0x08); //VertexZ + vertexBuffer[(i * 8) + 3] = ReadFloat(vertBlock, (i * vertexElemSize) + 0x0C); //NormX + vertexBuffer[(i * 8) + 4] = ReadFloat(vertBlock, (i * vertexElemSize) + 0x10); //NormY + vertexBuffer[(i * 8) + 5] = ReadFloat(vertBlock, (i * vertexElemSize) + 0x14); //NormZ + + vertexBuffer[(i * 8) + 6] = ReadFloat(uvBlock, (i * uvElemSize) + 0x00); //UVu + vertexBuffer[(i * 8) + 7] = ReadFloat(uvBlock, (i * uvElemSize) + 0x04); //UVv } return vertexBuffer; } diff --git a/LibReplanetizer/Models/TextureConfig.cs b/LibReplanetizer/Models/TextureConfig.cs index 65162f0..596178c 100644 --- a/LibReplanetizer/Models/TextureConfig.cs +++ b/LibReplanetizer/Models/TextureConfig.cs @@ -38,12 +38,12 @@ public WrapMode wrapModeS { if ((mode & 0b01) > 0) { - return (((mode & 0b10) > 0)) ? WrapMode.ClampEdge : WrapMode.Repeat; + return ((mode & 0b10) > 0) ? WrapMode.ClampEdge : WrapMode.Repeat; } if (((mode >> 24) & 0b01) > 0) { - return ((((mode >> 24) & 0b10) > 0)) ? WrapMode.ClampEdge : WrapMode.Repeat; + return (((mode >> 24) & 0b10) > 0) ? WrapMode.ClampEdge : WrapMode.Repeat; } return WrapMode.Repeat; @@ -55,10 +55,10 @@ public WrapMode wrapModeS switch (value) { case WrapMode.Repeat: - mode = mode & (~0b10); + mode &= (~0b10); break; case WrapMode.ClampEdge: - mode = mode | 0b10; + mode |= 0b10; break; default: break; @@ -71,10 +71,10 @@ public WrapMode wrapModeS switch (value) { case WrapMode.Repeat: - mode = mode & ~(0b10 << 24); + mode &= ~(0b10 << 24); break; case WrapMode.ClampEdge: - mode = mode | (0b10 << 24); + mode |= (0b10 << 24); break; default: break; @@ -91,12 +91,12 @@ public WrapMode wrapModeT { if (((mode >> 2) & 0b01) > 0) { - return ((((mode >> 2) & 0b10) > 0)) ? WrapMode.ClampEdge : WrapMode.Repeat; + return (((mode >> 2) & 0b10) > 0) ? WrapMode.ClampEdge : WrapMode.Repeat; } if (((mode >> 26) & 0b01) > 0) { - return ((((mode >> 26) & 0b10) > 0)) ? WrapMode.ClampEdge : WrapMode.Repeat; + return (((mode >> 26) & 0b10) > 0) ? WrapMode.ClampEdge : WrapMode.Repeat; } return WrapMode.Repeat; @@ -108,10 +108,10 @@ public WrapMode wrapModeT switch (value) { case WrapMode.Repeat: - mode = mode & ~(0b10 << 2); + mode &= ~(0b10 << 2); break; case WrapMode.ClampEdge: - mode = mode | (0b10 << 2); + mode |= (0b10 << 2); break; default: break; @@ -124,10 +124,10 @@ public WrapMode wrapModeT switch (value) { case WrapMode.Repeat: - mode = mode & ~(0b10 << 26); + mode &= ~(0b10 << 26); break; case WrapMode.ClampEdge: - mode = mode | (0b10 << 26); + mode |= (0b10 << 26); break; default: break; diff --git a/LibReplanetizer/Parsers/MobyloadParser.cs b/LibReplanetizer/Parsers/MobyloadParser.cs new file mode 100644 index 0000000..ba0e853 --- /dev/null +++ b/LibReplanetizer/Parsers/MobyloadParser.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2018-2023, The Replanetizer Contributors. +// Replanetizer is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// Please see the LICENSE.md file for more details. + +using LibReplanetizer.Headers; +using LibReplanetizer.Models; +using System; +using System.Collections.Generic; + +namespace LibReplanetizer.Parsers +{ + public class MobyloadParser : RatchetFileParser, IDisposable + { + MobyloadHeader mobyloadHead; + GameType game; + + public MobyloadParser(GameType game, string mobyloadFile) : base(mobyloadFile) + { + this.game = game; + mobyloadHead = new MobyloadHeader(fileStream); + } + + public List GetTextures() + { + return GetTexturesMobyload(mobyloadHead.texturePointer, mobyloadHead.textureDataPointer, mobyloadHead.textureCount); + } + + public List GetMobyModels() + { + List models = new List(); + + foreach (Tuple model in mobyloadHead.modelData) + { + // ID of zero implies that something wrong and this model is to be ignored. + if (model.Item2 != 0) + { + models.Add(new MobyModel(fileStream, game, (short) model.Item2, model.Item1)); + } + } + + return models; + + } + + public void Dispose() + { + fileStream.Close(); + } + } +} diff --git a/LibReplanetizer/Parsers/RatchetFileParser.cs b/LibReplanetizer/Parsers/RatchetFileParser.cs index 5c4d0ed..3b82b72 100644 --- a/LibReplanetizer/Parsers/RatchetFileParser.cs +++ b/LibReplanetizer/Parsers/RatchetFileParser.cs @@ -82,6 +82,35 @@ protected List GetTextures(int texturePointer, int textureCount) return textureList; } + protected List GetTexturesMobyload(int texturePointer, int textureDataPointer, int textureCount) + { + List textureList = new List(textureCount); + + //Read the whole texture header block, and add textures based on the count + byte[] textureBlock = ReadBlock(fileStream, texturePointer, textureCount * Texture.TEXTUREELEMSIZE); + for (int i = 0; i < textureCount; i++) + { + textureList.Add(new Texture(textureBlock, i)); + } + + for (int i = 0; i < textureList.Count; i++) + { + textureList[i].mipMapCount = 0; + int length; + if (i < textureList.Count - 1) + { + length = (int) (textureList[i + 1].vramPointer - textureList[i].vramPointer); + } + else + { + length = (int) (fileStream.Length - textureList[i].vramPointer); + } + textureList[i].data = ReadBlock(fileStream, textureDataPointer + textureList[i].vramPointer, length); + } + + return textureList; + } + protected List GetTies(List tieModels, int tiePointer, int tieCount) { List ties = new List(tieCount); diff --git a/README.md b/README.md index 0017b04..cd66733 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,8 @@ You can move around the world with keyboard and mouse: - Left click items to select them - Rotate the camera by holding the right mouse button down and moving your mouse +> **ⓘ** If your computer has both a dedicated and an onboard GPU, make sure to use the dedicated GPU. On Windows with a dedicated Nvidia GPU, you can do this by right clicking on Replanetizer.exe and selecting "Run with graphics processor" -> "High performance NVIDIA processor". + # Building Dependencies: diff --git a/Replanetizer/Frames/LevelFrame.cs b/Replanetizer/Frames/LevelFrame.cs index d0b0931..04a4827 100644 --- a/Replanetizer/Frames/LevelFrame.cs +++ b/Replanetizer/Frames/LevelFrame.cs @@ -574,6 +574,14 @@ void LoadLevelTextures() textureIds.Add(t, new GLTexture(t)); } } + + foreach (List textures in level.mobyloadTextures) + { + foreach (Texture t in textures) + { + textureIds.Add(t, new GLTexture(t)); + } + } } private void LoadLevel(Level level) diff --git a/Replanetizer/Frames/ModelFrame.cs b/Replanetizer/Frames/ModelFrame.cs index 65ab531..89382ff 100644 --- a/Replanetizer/Frames/ModelFrame.cs +++ b/Replanetizer/Frames/ModelFrame.cs @@ -52,6 +52,7 @@ public class ModelFrame : LevelSubFrame private List sortedShrubModels; private List sortedGadgetModels; private List> sortedMissionModels; + private List> sortedMobyloadModels; private List selectedObjectInstances = new List(); @@ -123,6 +124,11 @@ public ModelFrame(Window wnd, LevelFrame levelFrame, ShaderTable shaderIDTable, { sortedMissionModels.Add(new List(level.missions[i].models)); } + sortedMobyloadModels = new List>(); + for (int i = 0; i < level.mobyloadModels.Count; i++) + { + sortedMobyloadModels.Add(new List(level.mobyloadModels[i])); + } sortedMobyModels.Sort((x, y) => (x.id < y.id) ? -1 : 1); sortedTieModels.Sort((x, y) => (x.id < y.id) ? -1 : 1); @@ -132,6 +138,10 @@ public ModelFrame(Window wnd, LevelFrame levelFrame, ShaderTable shaderIDTable, { list.Sort((x, y) => (x.id < y.id) ? -1 : 1); } + foreach (List list in sortedMobyloadModels) + { + list.Sort((x, y) => (x.id < y.id) ? -1 : 1); + } UpdateWindowSize(); OnResize(); @@ -235,11 +245,21 @@ private void RenderTree() { for (int i = 0; i < sortedMissionModels.Count; i++) { - var mission = level.missions[i]; + Mission mission = level.missions[i]; RenderSubTree("Mission " + i, sortedMissionModels[i], mission.textures); } ImGui.TreePop(); } + if (ImGui.TreeNode("Mobyload")) + { + for (int i = 0; i < sortedMobyloadModels.Count; i++) + { + List textures = level.mobyloadTextures[i]; + if (textures.Count > 0) + RenderSubTree("Mobyload " + i, sortedMobyloadModels[i], textures); + } + ImGui.TreePop(); + } if (ImGui.TreeNode("Miscellaneous")) { RenderModelEntry(level.skybox, level.textures, "Skybox"); @@ -314,8 +334,8 @@ public override void Render(float deltaTime) System.Numerics.Vector2.UnitY, System.Numerics.Vector2.UnitX); ImGui.NextColumn(); - var colW = ImGui.GetColumnWidth() - 10; - var colSize = new System.Numerics.Vector2(colW, height); + float colW = ImGui.GetColumnWidth() - 10.0f; + System.Numerics.Vector2 colSize = new System.Numerics.Vector2(colW, height); if (ImGui.BeginChild("TextureAndPropertyView", colSize, false, ImGuiWindowFlags.AlwaysVerticalScrollbar)) { diff --git a/Replanetizer/Frames/TextureFrame.cs b/Replanetizer/Frames/TextureFrame.cs index e8ae46d..f97aafa 100644 --- a/Replanetizer/Frames/TextureFrame.cs +++ b/Replanetizer/Frames/TextureFrame.cs @@ -106,10 +106,9 @@ public override void Render(float deltaTime) { for (int i = 0; i < level.armorTextures.Count; i++) { - var textureList = level.armorTextures[i]; + List textureList = level.armorTextures[i]; if (ImGui.TreeNode("Armor " + i)) { - var offset = (int) ImGui.GetTreeNodeToLabelSpacing(); RenderTextureList(textureList, itemSizeX, levelFrame.textureIds); ImGui.TreePop(); } @@ -117,16 +116,31 @@ public override void Render(float deltaTime) } if (ImGui.CollapsingHeader("Mission textures")) { - foreach (var mission in level.missions) + foreach (Mission mission in level.missions) { if (ImGui.TreeNode("Mission " + mission.missionID)) { - var offset = (int) ImGui.GetTreeNodeToLabelSpacing(); RenderTextureList(mission.textures, itemSizeX, levelFrame.textureIds); ImGui.TreePop(); } } } + if (ImGui.CollapsingHeader("Mobyload textures")) + { + for (int i = 0; i < level.mobyloadTextures.Count; i++) + { + List textureList = level.mobyloadTextures[i]; + + if (textureList.Count > 0) + { + if (ImGui.TreeNode("Mobyload " + i)) + { + RenderTextureList(textureList, itemSizeX, levelFrame.textureIds); + ImGui.TreePop(); + } + } + } + } } } } diff --git a/Replanetizer/ModelLists/MobyModelsRC3.txt b/Replanetizer/ModelLists/MobyModelsRC3.txt index ada26f2..3c7c816 100644 --- a/Replanetizer/ModelLists/MobyModelsRC3.txt +++ b/Replanetizer/ModelLists/MobyModelsRC3.txt @@ -1,8 +1,17 @@ 0000=Ratchet 000A=Clank +000B=Weapon Vendor +01F4=Bolt Crate +01F5=Health Crate (SP) +01F7=Bonus Bolts Crate +01F9=Explosive Crate +01FF=Ammo Crate +046E=Titanium Bolt 05C9=Lava Gun 05CA=Plasma Storm 0825=Hypershot +0952=Dynamo Control Node +09B9=Obani Jump Pad 0A5D=Sheepinator 0A65=Megaturret Glove 0B37=Ocean @@ -10,14 +19,57 @@ 0C4A=Plasma Coil 0C59=Liquid Nitrogen Gun 0C5A=Miniturret Glove +0C60=Teleport Pad (Campaign) 0E14=Bouncer 0E9E=Heavy Bouncer 0EAD=Black Sheepinator +0F05=Jump Pad (SP) +0F51=Teleporter (Old Style) +0FA0=Television +106A=MP Player Config +107C=Turboslider +107E=Hovership +107F=bigass tank (vehicle) +108A=Gravity bomb launcher +108E=Gravity bomb (real one launched by launcher) +1090=Another Gravity bomb +109A=Roller Base Defense Bot +109D=Drone Bot +109E=Ranger Torso +109F=Ranger Feet +10A4=Lava Gun +10A7=Morph-O-ray +10A9=Holoshield +10C3=Teleporter Pad +10C4=Jump Pad +10C6=Siege Node (Unsure) +11C1=Obani Beam Director +1388=Ammo Pad +15A6=Galactic Ranger +15CA=Node Turret (small) +15EE=Health Pad +1607=Dynamo Platform +1632=Hoven Main Bridge Breakable Covering +1633=Hoven Main Bridge Breakable Covering +1634=Hoven Main Bridge Breakable Covering +1635=Hoven Main Bridge Breakable Covering +1636=Hoven Main Bridge Breakable Covering +1637=Hoven Main Bridge Breakable Covering +1638=Hoven Main Bridge Breakable Covering +1639=Hoven Main Bridge Breakable Covering +163A=Starship Computer Terminals +166F=Drone Bot Cluster Config +1672=Hoven Building Glass Platform +16DB=Snowman (Skin) +16E3=Darla Gratch +16FD=Galactic President +171C=Ratchet (Skin) 1843=Plasma Whip 184E=Spitting Hydra 184F=N90 Hurricane 1852=Glove of Doom 185B=Suck Cannon +1860=Refractor Lens 1861=Infector 1863=Shock Blaster 1864=Annihilator @@ -32,9 +84,168 @@ 1886=Infecto Bomb 1887=Decimator 1892=Vortex Cannon +189E=Flux Rifle Ammo Pack +189F=Mini Rocket Tube Ammo Pack +18B0=Ratchet (Chauffeur) 18BE=N60 Storm +18BF=Remote Control +18C0=VR Simulator Green Shock Field +18C9=VR Simulator Grey Platform Segment +18CA=VR Simulator Blue(?) Platform Segment +18CB=Robo (Skin) +18CC=Thug (Skin) +18CF=Thyrannoid (Skin) +18E2=Game System +18E3=Bridge Transport(unsure) +18EC=VR Simulator Spawning Chamber +1910=Starship Door +195B=Captain Qwark +195F=Starship Glass Platform (Small) +1961=Starship Glass Platform (Large) +1975=Ranger +1976=Head Commander Chair +1977=Lawrence +1981=Vehicle Pad +1983=4 Drones Platform (Hoven/Metropolis) +1987=VR Simulator +19A0=Sparks(unsure) +19AF=Hoven Bridge Side Piece +19B0=Acid/Water Polygon +19B2=Hoven Bridge Destroyed +19C4=Swingshot Orb +19CD=Teleporter (Story Mode) +19DE=Seige Node (Unsure) +19F2=Sasha +19F6=Rolling Drone Spawner +1A1B=Shock Droid +1A27=Bolt Crank +1A29=Hoven Bridge Center Piece +1A47=Node Column thing +1A63=Node Turret +1A77=Blue Force Field +1A91=Shock Droid Spawner +1ABA=Gravity Bomb Crate +1ABB=Mini Rocket Tube Crate +1ABC=Flux Rifle Crate +1ABD=Blitz Gun Crate +1ABE=Lava Gun Crate +1ABF=Holoshield Crate +1AC0=Morph-O-Ray Crate +1AC1=Mine Glove Crate +1AD6=Base Gattling Turret +1ADC=Ninja (skin) +1AE0=Hacker/Infiltrator Terminal +1AE1=Obani Glass Cylinder +1AE5=Obani Atmosphere Cloud +1AF2=Health Box +1AFC=Weapon Pack +1B02=Mine Glove Ammo Pack +1B03=Lava Gun Ammo Pack +1B05=N60 Storm Ammo Pack +1B09=Chargeboots Crate +1B23=Korgon Metal Bridge Segment +1B3B=Glass Circle Platform +1B43=Obani Bridge Frame 1B4F=Tempest +1B66=Helga +1B6C=Shock Droid (SP) +1B7B=Florana Tree Beast Mask +1B84=Banana +1B92=Obani Orbiting Asteroid +1BA4=Mirror +1BA8=Obani Satellite +1BBD=Anti-Aircraft Missle Turret +1BC3=Duck +1BD1=Big Al +1BD2=Skid McMarx +1BEA=Obani Metal Bridge +1BED=Obani Breakable Satellite +1BF6=Obani Trooper Enemy +1BF8=Obani Glass Dome +1C06=Qwark Videogame +1C08=Machine Gun Enemy +1C12=Skid McMarx +1C29=Skid McMarx (Obani) +1C2F=Red Flag +1C31=Blue Flag +1C38=Banana +1C41=Obani Green Force Field 1C44=Multi-Disc Gun +1C57=Base Computer 1C63=Qwack-O-Blitzer 1C67=Rift Inducer +1C7F=Blue Decorative Crate/Barricade +1C86=Television +1C8B=Game Controller +1C93=Biobliterator +1C9A=Shock Blaster +1C9B=Nitro Launcher +1C9C=Wrench +1CAF=Dr. Nefarious +1CB3=Hacker +1CC0=Lawrence (Musician) +1CF7=Force Field +1CFB=Gladiola (skin) +1CFC=Bruiser (Skin) +1CFD=Robo Rooster (Skin) +1CFE=Buginoid (Skin) +1D4D=Ratchet Trophy +1D69=Supernova Taxi Employee +1D6A=Magnet Boots +1D7B=Armor Vendor +1D90=SAC Movie Car +1D99=Ship Platform 1DE1=RYNOCIRATOR +1DE9=Skrunch +1DEB=Hypershot +1DEE=Dr. Nefarious +1DF0=Warp Pad +1DF1=Skrunch (Q-Force) +1E07=Hotbot (Skin) +1E41=Hoven Breakable Wall Decoration +1E45=Skid McMarx Weapon +1E4C=Brainius (Skin) +1E4D=Bones (Skin) +1E54=Datadisk +1E59=Trooper (Skin) +1E62=Qwark Videogame +1E63=Qwark Videogame +1E64=Qwark Videogame +1E65=Skrunch (Skin) +1E66=Remote Control +1E68=Gray (Skin) +1E69=Nefarious (Skin) +1E73=Skrunch (NPC) +1E77=Evil Clown Ratchet (Skin) +1E78=Beach Bunny Ratchet (Skin) +1E7A=Constructobot (Skin) +1E83=Dan (Skin) +1E96=Floor Light +1E97=Tank Pipe (Breakable) +1E98=Tank Pipe (Broken) +1E99=Small Console Computer +1E9C=Computer Monitor +1EA3=Tank Pipe Decoration (unsure) +1ECF=Computer Desk +1ED4=Metal Screw Mushroom +1ED6=Metal Flower +1EDC=Metal Light +1EE1=Obani Glass For Bridge +1F1E=Random Pickup Crate +1F32=Skid McMarx (Robot) +1F3C=Crotchitizer +1F40=Crowbar +1F43=Clank Holding Cell +1F48=Elevator +1F50=Courtney Gears Face +1F51=Courtney Gears Dancer +1F56=Q-Force Shuttle +1F5A=Splash Screen +1F5C=Galactic Rangers Dropship +1F6C=Biobliterator Head +1F6F=Crayon +1F71=Big Al +1F82=Tyhrra-Guise +1F85=Clank +1F8A=Gun Reticle +1F8B=Obani Energy Cloud diff --git a/Replanetizer/Replanetizer.csproj b/Replanetizer/Replanetizer.csproj index 3f19889..9a80433 100644 --- a/Replanetizer/Replanetizer.csproj +++ b/Replanetizer/Replanetizer.csproj @@ -38,13 +38,13 @@ - + - - - - - + + + + + diff --git a/Replanetizer/Utils/ImGuiController.cs b/Replanetizer/Utils/ImGuiController.cs index 6698961..30068cd 100644 --- a/Replanetizer/Utils/ImGuiController.cs +++ b/Replanetizer/Utils/ImGuiController.cs @@ -307,7 +307,7 @@ private void RenderImDrawData(ImDrawDataPtr drawData) for (int i = 0; i < drawData.CmdListsCount; i++) { - ImDrawListPtr cmdList = drawData.CmdListsRange[i]; + ImDrawListPtr cmdList = drawData.CmdLists[i]; int vertexSize = cmdList.VtxBuffer.Size * Unsafe.SizeOf(); if (vertexSize > vertexBufferSize) @@ -360,7 +360,7 @@ private void RenderImDrawData(ImDrawDataPtr drawData) // Render command lists for (int n = 0; n < drawData.CmdListsCount; n++) { - ImDrawListPtr cmdList = drawData.CmdListsRange[n]; + ImDrawListPtr cmdList = drawData.CmdLists[n]; GL.NamedBufferSubData(vertexBuffer, IntPtr.Zero, cmdList.VtxBuffer.Size * Unsafe.SizeOf(), cmdList.VtxBuffer.Data); GLUtil.CheckGlError($"Data Vert {n}"); diff --git a/Replanetizer/Utils/TextureIO.cs b/Replanetizer/Utils/TextureIO.cs index eca0d8c..613b31b 100644 --- a/Replanetizer/Utils/TextureIO.cs +++ b/Replanetizer/Utils/TextureIO.cs @@ -94,6 +94,15 @@ public static void ExportAllTextures(Level level, string path) ExportTexture(textures[j], Path.Join(path, $"mission_{i}_{j}.png"), true); } } + + for (int i = 0; i < level.mobyloadTextures.Count; i++) + { + List textures = level.missions[i].textures; + for (int j = 0; j < textures.Count; j++) + { + ExportTexture(textures[j], Path.Join(path, $"mobyload_{i}_{j}.png"), true); + } + } } } }