diff --git a/data/ObjectCombos_NA.json b/data/ObjectCombos_NA.json index b1770c9..0f2d814 100644 --- a/data/ObjectCombos_NA.json +++ b/data/ObjectCombos_NA.json @@ -52,12 +52,6 @@ "ModelAddress": "0x00000000", "Behavior": "0x13000494" }, - { - "Name": "Aquarium Bubble", - "ModelID": "0x00", - "ModelAddress": "0x00000000", - "Behavior": "0x13000494" - }, { "Name": "Arrow Lift", "ModelID": "0x37", @@ -70,12 +64,6 @@ "ModelAddress": "0x0C000104", "Behavior": "0x130020E8" }, - { - "Name": "Baby Penguin", - "ModelID": "0x57", - "ModelAddress": "0x0C000104", - "Behavior": "0x130020E8" - }, { "Name": "Bascule Bridge", "ModelID": "0x38", @@ -118,30 +106,12 @@ "ModelAddress": "0x0E0003A0", "Behavior": "0x13004D64" }, - { - "Name": "Big Rotating Gear", - "ModelID": "0x44", - "ModelAddress": "0x0E0003A0", - "Behavior": "0x13004D64" - }, { "Name": "Big Staircase Level Part", "ModelID": "0x04", "ModelAddress": "0x0E000820", "Behavior": "0x13002A48" }, - { - "Name": "Big Staircase Level Part", - "ModelID": "0x04", - "ModelAddress": "0x0E000820", - "Behavior": "0x13002A48" - }, - { - "Name": "Bird ambient sounds", - "ModelID": "0x00", - "ModelAddress": "0x00000000", - "Behavior": "0x13003C7C" - }, { "Name": "Bird ambient sounds", "ModelID": "0x00", @@ -160,30 +130,12 @@ "ModelAddress": "0x16000200", "Behavior": "0x13002588" }, - { - "Name": "Blue Coin", - "ModelID": "0x76", - "ModelAddress": "0x16000200", - "Behavior": "0x13002588" - }, { "Name": "Blue Coins Switch", "ModelID": "0x8C", "ModelAddress": "0x0F000000", "Behavior": "0x13002568" }, - { - "Name": "Blue Coins Switch", - "ModelID": "0x8C", - "ModelAddress": "0x0F000000", - "Behavior": "0x13002568" - }, - { - "Name": "Blue Elevator Platform", - "ModelID": "0x40", - "ModelAddress": "0x0E0008F0", - "Behavior": "0x13000CFC" - }, { "Name": "Blue Elevator Platform", "ModelID": "0x40", @@ -196,12 +148,6 @@ "ModelAddress": "0x16000B8C", "Behavior": "0x13000C84" }, - { - "Name": "Blue Flame", - "ModelID": "0x91", - "ModelAddress": "0x16000B8C", - "Behavior": "0x13000C84" - }, { "Name": "Blue Smiley", "ModelID": "0x37", @@ -232,12 +178,6 @@ "ModelAddress": "0x0C000224", "Behavior": "0x13002790" }, - { - "Name": "Boo Buddy", - "ModelID": "0x54", - "ModelAddress": "0x0C000224", - "Behavior": "0x130027D0" - }, { "Name": "Boo Buddy 2", "ModelID": "0x54", @@ -686,7 +626,10 @@ "Name": "Coin Formation", "ModelID": "0x00", "ModelAddress": "0x00000000", - "Behavior": "0x130008EC" + "Behavior": "0x130008EC", + "BP2_NAME": "Content", + "BP2_DESCRIPTION": "0: Five coins horizontal\n2: Coin ring horizontal\n4: Coin arrow\n16: Five coins horizontal flying\n17: Five coins vertical\n18: Coin ring horizontal flying\n19: Coin ring vertical" + }, { "Name": "Coins", @@ -2639,7 +2582,7 @@ "Behavior": "0x13002F60" }, { - "Name": "Warp", + "Name": "Warp (for level exit)", "ModelID": "0x00", "ModelAddress": "0x00000000", "Behavior": "0x13002F84" @@ -2925,6 +2868,152 @@ "ModelID": "0x55", "ModelAddress": "0x0C000468", "Behavior": "0x13004538" + }, + { + "Name": "Beta Blarrg [MOP1]", + "ModelID": "0x54", + "ModelAddress": "0x0C000224", + "Behavior": "0x130023D0" + }, + { + "Name": "Trampoline [MOP1]", + "ModelID": "0xB5", + "ModelAddress": "0x0C000000", + "Behavior": "0x13001608" + }, + { + "Name": "Noteblock [MOP1]", + "ModelID": "0x7B", + "ModelAddress": "0x0301dbf8", + "Behavior": "0x13000174" + }, + { + "Name": "Sandblock [MOP1]", + "ModelID": "0x99", + "ModelAddress": "0x030225e4", + "Behavior": "0x1300064C" + }, + { + "Name": "Shrinkplatform [MOP1]", + "ModelID": "0x98", + "ModelAddress": "0x030212f4", + "Behavior": "0x13000624" + }, + { + "Name": "Spring [MOP1]", + "ModelID": "0x92", + "ModelAddress": "0x0301fc98", + "Behavior": "0x130005B4" + }, + { + "Name": "Shell 1 [MOP1]", + "ModelID": "0x9B", + "ModelAddress": "0x0f000adc", + "Behavior": "0x13004218" + }, + { + "Name": "Shell 2 [MOP1]", + "ModelID": "0x9D", + "ModelAddress": "0x0f000b08", + "Behavior": "0x13004218" + }, + { + "Name": "Emitter [MOP2]", + "ModelID": "0x00", + "ModelAddress": "0x00000000", + "Behavior": "0x130050B4", + "BP1_NAME": "Param 1", + "BP2_NAME": "Param 2", + "BP1_DESCRIPTION": "Spawn radius, Red - value", + "BP2_DESCRIPTION": "Green - value, Blue - value" + }, + { + "Name": "Flipclock [MOP2]", + "ModelID": "0xF0", + "ModelAddress": "0x0302272c", + "Behavior": "0x130050D0" + }, + { + "Name": "Jukebox [MOP2]", + "ModelID": "0x00", + "ModelAddress": "0x00000000", + "Behavior": "0x13005104", + "BP1_NAME": "First", + "BP2_NAME": "Last", + "BP1_DESCRIPTION": "First song in list", + "BP2_DESCRIPTION": "Last song in list" + }, + { + "Name": "PSwitch [MOP2]", + "ModelID": "0xCF", + "ModelAddress": "0x0f0004cc", + "Behavior": "0x1300512C" + }, + { + "Name": "Switch for Switchblocks [MOP2]", + "ModelID": "0xF2", + "ModelAddress": "0x03022708", + "Behavior": "0x13003AE0", + "BP2_NAME": "Color", + "BP2_DESCRIPTION": "0 for red\n1 for blue" + }, + { + "Name": "Switchblock [MOP2]", + "ModelID": "0xF1", + "ModelAddress": "0x030226d4", + "Behavior": "0x13004EA0", + "BP2_NAME": "Color", + "BP2_DESCRIPTION": "0 for red\n2 for blue", + "BP1_NAME": "Start Color", + "BP1_DESCRIPTION": "0 to start red\n2 to start blue" + }, + { + "Name": "Checkpoint Flag [MOP3]", + "ModelID": "0x2E", + "ModelAddress": "0x00606660", + "Behavior": "0x13000D50", + "BP2_NAME": "Flag", + "BP2_DESCRIPTION": "0 for regular flag\n1 for reset flag" + }, + { + "Name": "Moving & Rotating Block [MOP3]", + "ModelID": "0x2D", + "ModelAddress": "0x00603670", + "Behavior": "0x13000D24", + "BP1_NAME": "Color", + "BP1_DESCRIPTION": "0 for blue\n1 for red", + "BP2_NAME": "PathID", + "BP2_DESCRIPTION": "Path ID (0, 1 and 2 are predefined)" + }, + { + "Name": "Flipswitch Panel [MOP3]", + "ModelID": "0x2A", + "ModelAddress": "0x005f9fe0", + "Behavior": "0x130005D8" + }, + { + "Name": "Flipswitch Panel Starspawner [MOP3]", + "ModelID": "0x00", + "ModelAddress": "0x00000000", + "Behavior": "0x130002A0", + "BP1_NAME": "Star #", + "BP1_DESCRIPTION": "Star number" + }, + { + "Name": "Green Switchboard [MOP3]", + "ModelID": "0x2B", + "ModelAddress": "0x005fd8b0", + "Behavior": "0x13000CFC", + "BP1_NAME": "Direct 1", + "BP1_DESCRIPTION": "Maximum distance into direction1", + "BP2_NAME": "Direct 2", + "BP2_DESCRIPTION": "Maximum distance into direction2" + }, + { + "Name": "Flipswap Platform [MOP3]", + "ModelID": "0x2F", + "ModelAddress": "0x005f9ac0", + "Behavior": "0x13000278" } ] } \ No newline at end of file diff --git a/src/Forms/MainForm.cs b/src/Forms/MainForm.cs index b77c3da..be49bd7 100644 --- a/src/Forms/MainForm.cs +++ b/src/Forms/MainForm.cs @@ -508,7 +508,7 @@ private void saveROMAsToolStripMenuItem_Click(object sender, EventArgs e) private void saveROMToolStripMenuItem_Click(object sender, EventArgs e) { - ROM.Instance.saveFileAs(ROM.Instance.Filepath, ROM.Instance.Endian); + ROM.Instance.saveFile(); } private void settingsToolStripMenuItem_Click(object sender, EventArgs e) @@ -534,6 +534,14 @@ private void replaceObject(int index, ref SelectComboPreset comboWindow) area.Objects[index].setBehaviorFromAddress(comboWindow.ReturnObjectCombo.Behavior); treeView1.Nodes[0].Nodes[index].Text = area.Objects[index].getObjectComboName(); area.Objects[index].SetBehaviorParametersToZero(); + area.Objects[index].Act1 = true; + area.Objects[index].Act2 = true; + area.Objects[index].Act3 = true; + area.Objects[index].Act4 = true; + area.Objects[index].Act5 = true; + area.Objects[index].Act6 = false; + area.Objects[index].AllActs = true; + area.Objects[index].ShowHideActs(true); area.Objects[index].UpdateProperties(); } @@ -680,6 +688,8 @@ private void objectComboPresetToolStripMenuItem_Click(object sender, EventArgs e glControl1.Invalidate(); propertyGrid1.Refresh(); glControl1.Update(); // Needed after calling propertyGrid1.Refresh(); + updateSelectedObjectsInROM(); + Globals.needToSave = true; } private void Form1_Shown(object sender, EventArgs e) @@ -1069,7 +1079,19 @@ private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEv if (obj == null) return; if (label.Equals("All Acts")) { - obj.ShowHideActs((bool)e.ChangedItem.Value); + bool isAllActs = (bool)e.ChangedItem.Value; + obj.ShowHideActs(isAllActs); + + if (isAllActs) + { + obj.Act1 = true; + obj.Act2 = true; + obj.Act3 = true; + obj.Act4 = true; + obj.Act5 = true; + obj.Act6 = false; + } + propertyGrid1.Refresh(); } else if (label.Equals("Behavior") || label.Equals("Model ID")) @@ -1111,7 +1133,24 @@ private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEv if (e.ChangedItem.Label.Equals("Behavior")) if (!obj.canEditBehavior) continue; - + + if (e.ChangedItem.Label.Equals("All Acts")) + { + bool isAllActs = (bool)e.ChangedItem.Value; + obj.ShowHideActs(isAllActs); + + if (isAllActs) + { + obj.Act1 = true; + obj.Act2 = true; + obj.Act3 = true; + obj.Act4 = true; + obj.Act5 = true; + obj.Act6 = false; + } + + propertyGrid1.Refresh(); + } obj.updateROMData(); } } diff --git a/src/ROM.cs b/src/ROM.cs index 757ab7d..7a012d5 100644 --- a/src/ROM.cs +++ b/src/ROM.cs @@ -42,6 +42,7 @@ class ROM public string filepath = ""; public string Filepath { get { return filepath; } } private byte[] bytes; + private byte[] writeMask; private uint[] segStart = new uint[0x20]; private bool[] segIsMIO0 = new bool[0x20]; private byte[][] segData = new byte[0x20][]; @@ -134,6 +135,10 @@ private void swapMixedBig() byte temp = bytes[i]; bytes[i] = bytes[i + 1]; bytes[i + 1] = temp; + + temp = writeMask[i]; + writeMask[i] = writeMask[i + 1]; + writeMask[i + 1] = temp; } } @@ -150,6 +155,15 @@ private void swapLittleBig() bytes[i + 1] = temp[2]; bytes[i + 2] = temp[1]; bytes[i + 3] = temp[0]; + + temp[0] = writeMask[i + 0]; + temp[1] = writeMask[i + 1]; + temp[2] = writeMask[i + 2]; + temp[3] = writeMask[i + 3]; + writeMask[i + 0] = temp[3]; + writeMask[i + 1] = temp[2]; + writeMask[i + 2] = temp[1]; + writeMask[i + 3] = temp[0]; } } @@ -211,10 +225,26 @@ public string getInternalName() return System.Text.Encoding.Default.GetString(getSubArray_safe(Bytes, 0x20, 20)); } + public void WriteToFileEx() + { + FileStream stream = File.OpenWrite(filepath); + for (int i = 0; i < bytes.Length; i++) + { + if (writeMask[i] != 0) + { + writeMask[i] = 0; + stream.Seek(i, SeekOrigin.Begin); + stream.WriteByte(bytes[i]); + } + } + stream.Close(); + } + public void readFile(string filename) { filepath = filename; bytes = File.ReadAllBytes(filename); + writeMask = new byte[bytes.Length]; checkROM(); Globals.pathToAutoLoadROM = filepath; Globals.needToSave = false; @@ -226,18 +256,18 @@ public void saveFile() if (Endian == ROM_Endian.MIXED) { swapMixedBig(); - File.WriteAllBytes(filepath, bytes); + WriteToFileEx(); swapMixedBig(); } else if (Endian == ROM_Endian.LITTLE) { swapLittleBig(); - File.WriteAllBytes(filepath, bytes); + WriteToFileEx(); swapLittleBig(); } else // Save as big endian by default { - File.WriteAllBytes(filepath, bytes); + WriteToFileEx(); } Globals.pathToAutoLoadROM = filepath; Globals.needToSave = false; @@ -458,13 +488,21 @@ private int SearchBytes(byte[] haystack, byte[] needle) return -1; } + private void addToWriteMask(uint start, int length) + { + for (int i = 0; i < length; i++) + writeMask[i + start] = 1; + } + public void writeByteArray(uint offset, byte[] arr) { + addToWriteMask(offset, arr.Length); Array.Copy(arr, 0, bytes, offset, arr.Length); } public void writeByteArray(uint offset, byte[] arr, int arr_offset, int arr_length) { + addToWriteMask(offset, arr.Length); Array.Copy(arr, arr_offset, bytes, offset, arr_length); } @@ -477,6 +515,7 @@ public void writeByteArrayToSegment(uint segAddr, byte[] arr) public void writeWord(uint offset, int word) { + addToWriteMask(offset, 4); bytes[offset + 0] = (byte)(word >> 24); bytes[offset + 1] = (byte)(word >> 16); bytes[offset + 2] = (byte)(word >> 8); @@ -490,6 +529,7 @@ public void writeWord(uint offset, uint word) public void writeHalfword(uint offset, short half) { + addToWriteMask(offset, 2); bytes[offset + 0] = (byte)(half >> 8); bytes[offset + 1] = (byte)(half); } @@ -501,6 +541,7 @@ public void writeHalfword(uint offset, ushort word) public void writeByte(uint offset, byte b) { + addToWriteMask(offset, 1); bytes[offset] = b; } @@ -631,37 +672,37 @@ public void findAndSetSegment02() public Dictionary levelIDs = new Dictionary { - { "Big Boo's Haunt", 0x04 }, - { "Cool Cool Mountain", 0x05 }, - { "Inside Castle", 0x06 }, - { "Hazy Maze Cave", 0x07 }, - { "Shifting Sand Land", 0x08 }, - { "Bob-omb Battlefield", 0x09 }, - { "Snowman's Land", 0x0A }, - { "Wet Dry World", 0x0B }, - { "Jolly Roger Bay", 0x0C }, - { "Tiny Huge Island", 0x0D }, - { "Tick Tock Clock", 0x0E }, - { "Rainbow Ride", 0x0F }, - { "Castle Grounds", 0x10 }, - { "Bowser Course 1", 0x11 }, - { "Vanish Cap", 0x12 }, - { "Bowser Course 2", 0x13 }, - { "Secret Aquarium", 0x14 }, - { "Bowser Course 3", 0x15 }, - { "Lethal Lava Land", 0x16 }, - { "Dire Dire Docks", 0x17 }, - { "Whomp's Fortress", 0x18 }, - { "End Cake Picture", 0x19 }, - { "Castle Courtyard", 0x1A }, - { "Peach's Secret Slide", 0x1B }, - { "Metal Cap", 0x1C }, - { "Wing Cap", 0x1D }, - { "Bowser Battle 1", 0x1E }, - { "Rainbow Clouds", 0x1F }, - { "Bowser Battle 2", 0x21 }, - { "Bowser Battle 3", 0x22 }, - { "Tall Tall Mountain", 0x24 } + { "[C01] Bob-omb Battlefield", 0x09 }, + { "[C02] Whomp's Fortress", 0x18 }, + { "[C03] Jolly Roger Bay", 0x0C }, + { "[C04] Cool Cool Mountain", 0x05 }, + { "[C05] Big Boo's Haunt", 0x04 }, + { "[C06] Hazy Maze Cave", 0x07 }, + { "[C07] Lethal Lava Land", 0x16 }, + { "[C08] Shifting Sand Land", 0x08 }, + { "[C09] Dire Dire Docks", 0x17 }, + { "[C10] Snowman's Land", 0x0A }, + { "[C11] Wet Dry World", 0x0B }, + { "[C12] Tall Tall Mountain", 0x24 }, + { "[C13] Tiny Huge Island", 0x0D }, + { "[C14] Tick Tock Clock", 0x0E }, + { "[C15] Rainbow Ride", 0x0F }, + { "[OW1] Castle Grounds", 0x10 }, + { "[OW2] Inside Castle", 0x06 }, + { "[OW3] Castle Courtyard", 0x1A }, + { "[BC1] Bowser Course 1", 0x11 }, + { "[BC2] Bowser Course 2", 0x13 }, + { "[BC3] Bowser Course 3", 0x15 }, + { "[MCL] Metal Cap", 0x1C }, + { "[WCL] Wing Cap", 0x1D }, + { "[VCL] Vanish Cap", 0x12 }, + { "[BB1] Bowser Battle 1", 0x1E }, + { "[BB2] Bowser Battle 2", 0x21 }, + { "[BB3] Bowser Battle 3", 0x22 }, + { "[SC1] Secret Aquarium", 0x14 }, + { "[SC2] Rainbow Clouds", 0x1F }, + { "[SC3] End Cake Picture", 0x19 }, + { "[SlC] Peach's Secret Slide", 0x1B } }; }