public static void DecodeLevelScripts(ROM SM64ROM, UInt32 offset) { ROMManager.ReadytoLoad = false; for (UInt32 i = offset; i < SM64ROM.getEndROMAddr();) { uint increment = SM64ROM.getByte(i + 1); /*using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"e:\test4.txt", true)) * { * file.Write(i.ToString("x") + ": "); * for (uint j = i; j < i + increment; j++) * { * file.Write(SM64ROM.getByte(j).ToString("x") + " "); * } * file.WriteLine("\n"); * file.Close(); * }*/ if (increment == 0 || SM64ROM.getByte(i) > 0x3C || ExitDecode) { return; } switch (SM64ROM.getByte(i)) { case 0x00: case 0x01: NewSegment = SM64ROM.getByte(i + 3); NewSegAddr = SM64ROM.ReadFourBytes(i + 4); SM64ROM.setSegment(NewSegment, NewSegAddr); //if (NewSegment != 0x0E) break; JumpSegAddr = SM64ROM.ReadFourBytes(i + 12); JumpAddr = SM64ROM.readSegmentAddr(JumpSegAddr); //i = JumpAddr -increment; LevelScripts.DecodeLevelScripts(SM64ROM, JumpAddr); break; case 0x02: if (!GeoFound) { break; } ExitDecode = true; GeoFound = false; ROMManager.ReadytoLoad = true; return; case 0x03: //delayframes break; case 0x04: //delayframes break; case 0x05: JumpSegAddr = SM64ROM.ReadFourBytes(i + 4); //i = SM64ROM.readSegmentAddr(JumpSegAddr)-increment; LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x06: JumpSegAddr = SM64ROM.ReadFourBytes(i + 4); //i = SM64ROM.readSegmentAddr(JumpSegAddr) - increment; LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x07: return; case 0x0C: if (SM64ROM.getByte(i + 7) != SelectedLevel + 4) { break; //num is level ID } JumpSegAddr = SM64ROM.ReadFourBytes(i + 8); LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); return; case 0x16: //Loads directly to ram, no segment break; case 0x17: NewSegment = SM64ROM.getByte(i + 3); NewSegAddr = SM64ROM.ReadFourBytes(i + 4); SM64ROM.setSegment(NewSegment, NewSegAddr); if (NewSegment == 0x0E) { Ext0EBankEnd = SM64ROM.ReadFourBytes(i + 8); } break; case 0x18: //MIO0 segment case 0x1A: //MIO0 segment NewSegment = SM64ROM.getByte(i + 3); BeginMIO0 = SM64ROM.ReadFourBytes(i + 4); NewSegAddr = SM64ROM.ReadFourBytes(BeginMIO0 + 12) + BeginMIO0; SM64ROM.setSegment(NewSegment, NewSegAddr); break; case 0x1F: //LEVEL MODEL uint SegAddr = SM64ROM.ReadFourBytes(i + 4); if (SM64ROM.getByte(i + 4) == 0x0E || SM64ROM.getByte(i + 4) == 0x19) //Level bank { Array.Resize(ref GeoLayoutOffsets, GeoLayoutOffsets.Length + 1); GeoLayoutOffsets[SM64ROM.getByte(i + 2) - 1] = SM64ROM.readSegmentAddr(SegAddr); GeoFound = true; if (SelectedLevel == 21) { return; // End Cake Loop evasion } break; } break; case 0x21: //obj model w/o geolayout break; case 0x22: //obj model w/ geolayout break; case 0x2E: ExtCollisionPointer = i; //Needed to repoint for extended roms break; default: break; } i += increment; } }
public static void DecodeLevelScripts(ROM SM64ROM, UInt32 offset) { ROMManager.ReadytoLoad = false; for (UInt32 i = offset; i < SM64ROM.getEndROMAddr();) { uint increment = SM64ROM.getByte(i + 1); if (ROMManager.debug) { Array.Resize(ref DebugScript, DebugScript.Length + 1); DebugScript[DebugScript.Length - 1] = i.ToString("x") + ": "; for (uint j = i; j < i + increment; j++) { DebugScript[DebugScript.Length - 1] += SM64ROM.getByte(j).ToString("x") + " "; } } if (increment == 0 || SM64ROM.getByte(i) > 0x3C || ExitDecode) { return; } switch (SM64ROM.getByte(i)) { case 0x00: case 0x01: NewSegment = SM64ROM.getByte(i + 3); NewSegAddr = SM64ROM.ReadFourBytes(i + 4); SM64ROM.setSegment(NewSegment, NewSegAddr); //if (NewSegment != 0x0E) break; JumpSegAddr = SM64ROM.ReadFourBytes(i + 12); JumpAddr = SM64ROM.readSegmentAddr(JumpSegAddr); //i = JumpAddr -increment; LevelScripts.DecodeLevelScripts(SM64ROM, JumpAddr); break; case 0x02: if (!GeoFound) { break; } ExitDecode = true; GeoFound = false; ROMManager.ReadytoLoad = true; return; case 0x03: //delayframes break; case 0x04: //delayframes break; case 0x05: JumpSegAddr = SM64ROM.ReadFourBytes(i + 4); //i = SM64ROM.readSegmentAddr(JumpSegAddr)-increment; LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x06: JumpSegAddr = SM64ROM.ReadFourBytes(i + 4); //i = SM64ROM.readSegmentAddr(JumpSegAddr) - increment; LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x07: return; case 0x0C: if (SM64ROM.getByte(i + 7) != SelectedLevel + 4) { break; //num is level ID } JumpSegAddr = SM64ROM.ReadFourBytes(i + 8); LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); return; case 0x16: //Loads directly to ram, no segment break; case 0x17: NewSegment = SM64ROM.getByte(i + 3); NewSegAddr = SM64ROM.ReadFourBytes(i + 4); SM64ROM.setSegment(NewSegment, NewSegAddr); if (NewSegment == 0x0E) { Ext0EBankEnd = SM64ROM.ReadFourBytes(i + 8); Console.Write("Segment 0x0E Location in ROM:\n0x" + SM64ROM.getSegmentStart(0x0E).ToString("x8")); } break; case 0x18: //MIO0 segment case 0x1A: //MIO0 segment NewSegment = SM64ROM.getByte(i + 3); BeginMIO0 = SM64ROM.ReadFourBytes(i + 4); NewSegAddr = SM64ROM.ReadFourBytes(BeginMIO0 + 12) + BeginMIO0; SM64ROM.setSegment(NewSegment, NewSegAddr); break; case 0x1F: //LEVEL MODEL uint SegAddr = SM64ROM.ReadFourBytes(i + 4); if (SM64ROM.getByte(i + 4) == 0x0E || SM64ROM.getByte(i + 4) == 0x19) //Level bank { Array.Resize(ref GeoLayoutOffsets, GeoLayoutOffsets.Length + 1); GeoLayoutOffsets[SM64ROM.getByte(i + 2) - 1] = SM64ROM.readSegmentAddr(SegAddr); GeoFound = true; if (SelectedLevel == 21) { return; // End Cake Loop evasion } break; } break; case 0x21: //obj model w/o geolayout break; case 0x22: int seg = SM64ROM.getByte(i + 4); Array.Resize(ref ObjectGeoOffsets[seg], ObjectGeoOffsets[seg].Length + 1); uint OBJSegAddr = SM64ROM.ReadFourBytes(i + 4); ObjectGeoOffsets[seg][ObjectGeoOffsets[seg].Length - 1] = SM64ROM.readSegmentAddr(OBJSegAddr); //obj model w/ geolayout break; case 0x2B: //Default Mario Position short YRotation = (short)SM64ROM.ReadTwoBytes(i + 4); int X = (short)-SM64ROM.ReadTwoBytes(i + 6); int Y = (short)SM64ROM.ReadTwoBytes(i + 8) + 250; //+250 to be above ground int Z = (short)-SM64ROM.ReadTwoBytes(i + 10); Vector3 location = new Vector3(X, Y, Z) * Renderer.WorldScale * Renderer.GameScale; Renderer.cam.SetCamPosition(location); float YRotRadians = Convert.ToSingle(YRotation) / 180f * Convert.ToSingle(Math.PI); Renderer.cam.SetCamOrientation(new Vector3(-YRotRadians - Convert.ToSingle(Math.PI / 2), 0f, YRotRadians)); break; case 0x2E: ExtCollisionPointer = i; //Needed to repoint for extended roms break; default: break; } i += increment; } }
public static void DecodeLevelScripts(ROM SM64ROM, UInt32 offset) { for (UInt32 i = offset; i < SM64ROM.getEndROMAddr();) { if (DebugScript.Length > 10000) { ExitDecode = true; } if (ExitDecode) { return; } uint increment = SM64ROM.getByte(i + 1); if (increment == 0 || SM64ROM.getByte(i) > 0x3C) { return; } Array.Resize(ref LevelScripts.DebugScript, LevelScripts.DebugScript.Length + 1); uint newindex = (uint)(LevelScripts.DebugScript.Length - 1); for (uint j = 0; j < stackcounter; j++) { LevelScripts.DebugScript[newindex] += " "; //tab further each stack increase for debug txt } LevelScripts.DebugScript[newindex] += i.ToString("x") + ": "; for (uint j = i; j < i + increment; j++) { LevelScripts.DebugScript[newindex] += SM64ROM.getByte(j).ToString("x2") + " "; } SkipCMDDetermination(i); //see if the command has already been processed before if (!skipCMD) { switch (SM64ROM.getByte(i)) //if not skipping command, process it { case 0x00: //Load raw data and jump NewSegment = SM64ROM.getByte(i + 3); NewSegAddr = SM64ROM.ReadFourBytes(i + 4); SM64ROM.setSegment(NewSegment, NewSegAddr); JumpSegAddr = SM64ROM.ReadFourBytes(i + 12); if (CheckExistingJumps(SM64ROM.readSegmentAddr(JumpSegAddr))) { break; //Don't jump to a spot previously jumped to } stackcounter++; LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x01: //Load raw data and jump NewSegment = SM64ROM.getByte(i + 3); NewSegAddr = SM64ROM.ReadFourBytes(i + 4); SM64ROM.setSegment(NewSegment, NewSegAddr); JumpSegAddr = SM64ROM.ReadFourBytes(i + 12); if (CheckExistingJumps(SM64ROM.readSegmentAddr(JumpSegAddr))) { break; //Don't jump to a spot previously jumped to } LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x02: //End level data return; case 0x03: //delayframes break; case 0x04: //delayframes break; case 0x05: //Jump to addr JumpSegAddr = SM64ROM.ReadFourBytes(i + 4); if (SM64ROM.readSegmentAddr(JumpSegAddr) == (i - 4)) { return; //The cake is a f*****g lie } if (CheckExistingJumps(SM64ROM.readSegmentAddr(JumpSegAddr))) { break; //Don't jump to a spot previously jumped to } LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x06: //Push stack JumpSegAddr = SM64ROM.ReadFourBytes(i + 4); if (CheckExistingJumps(SM64ROM.readSegmentAddr(JumpSegAddr))) { break; //Don't jump to a spot previously jumped to } stackcounter++; LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x07: //Pop stack stackcounter--; return; case 0x0B: //Conditional Pop break; case 0x0C: //Conditional Jump LevelID = SM64ROM.getByte(i + 7); if (LevelID == 0xFF) { break; } //if (LevelID == 0x00) throw new Exception(SM64ROM.getSegmentStart(0x14).ToString("x")); if (LevelID < 5) { SM64ROM.BackupAllSegments(); } SM64ROM.LoadBackupSegments(); JumpSegAddr = SM64ROM.ReadFourBytes(i + 8); if (CheckExistingJumps(SM64ROM.readSegmentAddr(JumpSegAddr))) { break; //Don't jump to a spot previously jumped to } LevelScripts.DecodeLevelScripts(SM64ROM, SM64ROM.readSegmentAddr(JumpSegAddr)); break; case 0x0D: //Conditional Push break; case 0x0E: //Conditional Skip break; case 0x0F: //Skip next break; case 0x10: //No-op break; case 0x11: //Set Accumulator From ASM break; case 0x12: //Actively set accumulator break; case 0x13: //Set accumulator break; case 0x16: //Loads directly to ram, no segment break; case 0x17: NewSegment = SM64ROM.getByte(i + 3); NewSegAddr = SM64ROM.ReadFourBytes(i + 4); SM64ROM.setSegment(NewSegment, NewSegAddr); break; case 0x18: //MIO0 segment case 0x1A: //MIO0 segment NewSegment = SM64ROM.getByte(i + 3); BeginMIO0 = SM64ROM.ReadFourBytes(i + 4); NewSegAddr = SM64ROM.ReadFourBytes(BeginMIO0 + 12) + BeginMIO0; SM64ROM.setSegment(NewSegment, NewSegAddr); break; case 0x1F: //LEVEL MODEL uint SegAddr = SM64ROM.ReadFourBytes(i + 4); GeoLayouts.DecodeGeoLayout(SM64ROM, SM64ROM.readSegmentAddr(SegAddr)); break; case 0x21: uint DLSegAddr = SM64ROM.ReadFourBytes(i + 4); DLConversion.ConvertDL(SM64ROM, DLSegAddr, false); break; case 0x22: uint ModelSegAddr = SM64ROM.ReadFourBytes(i + 4); GeoLayouts.DecodeGeoLayout(SM64ROM, SM64ROM.readSegmentAddr(ModelSegAddr)); break; case 0x2B: //Default Mario Position break; case 0x2E: //Collision break; default: break; } } i += increment; } }