public string CreateRom() { int flag = 0; // Get all the necessary level pointer ROM addresses and data location offsets for regular levels BinaryReader oldRom = new BinaryReader(File.OpenRead(oldRomPath)); BinaryReader regAddressReader = new BinaryReader(File.OpenRead("regular.dat")); List <AddressGroup> regAddressGroups = new List <AddressGroup>(); List <DataGroup> regDataGroups = new List <DataGroup>(); while (regAddressReader.BaseStream.Position != regAddressReader.BaseStream.Length) { AddressGroup currentAGroup = new AddressGroup(); currentAGroup.setPointer = regAddressReader.ReadUInt32(); currentAGroup.enemyPointer = regAddressReader.ReadUInt32(); currentAGroup.objectPointer = regAddressReader.ReadUInt32(); DataGroup currentDGroup = new DataGroup(); oldRom.BaseStream.Seek(currentAGroup.setPointer, SeekOrigin.Begin); currentDGroup.setData = (byte)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.enemyPointer, SeekOrigin.Begin); currentDGroup.enemyData = (ushort)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.objectPointer, SeekOrigin.Begin); currentDGroup.objectData = (ushort)oldRom.ReadUInt32(); if (levelFlags[flag++] == true) { regAddressGroups.Add(currentAGroup); regDataGroups.Add(currentDGroup); } } regAddressReader.Close(); mt.Shuffle(regDataGroups); // Repeat above for fortresses BinaryReader fortAddressReader = new BinaryReader(File.OpenRead("fort.dat")); List <AddressGroup> fortAddressGroups = new List <AddressGroup>(); List <DataGroup> fortDataGroups = new List <DataGroup>(); while (fortAddressReader.BaseStream.Position != fortAddressReader.BaseStream.Length) { AddressGroup currentAGroup = new AddressGroup(); currentAGroup.setPointer = fortAddressReader.ReadUInt32(); currentAGroup.enemyPointer = fortAddressReader.ReadUInt32(); currentAGroup.objectPointer = fortAddressReader.ReadUInt32(); DataGroup currentDGroup = new DataGroup(); oldRom.BaseStream.Seek(currentAGroup.setPointer, SeekOrigin.Begin); currentDGroup.setData = (byte)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.enemyPointer, SeekOrigin.Begin); currentDGroup.enemyData = (ushort)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.objectPointer, SeekOrigin.Begin); currentDGroup.objectData = (ushort)oldRom.ReadUInt32(); if (levelFlags[flag++] == true) { fortAddressGroups.Add(currentAGroup); fortDataGroups.Add(currentDGroup); } } fortAddressReader.Close(); mt.Shuffle(fortDataGroups); // Repeat above for castles BinaryReader castleAddressReader = new BinaryReader(File.OpenRead("castle.dat")); List <AddressGroup> castleAddressGroups = new List <AddressGroup>(); List <DataGroup> castleDataGroups = new List <DataGroup>(); while (castleAddressReader.BaseStream.Position != castleAddressReader.BaseStream.Length) { AddressGroup currentAGroup = new AddressGroup(); currentAGroup.setPointer = castleAddressReader.ReadUInt32(); currentAGroup.enemyPointer = castleAddressReader.ReadUInt32(); currentAGroup.objectPointer = castleAddressReader.ReadUInt32(); DataGroup currentDGroup = new DataGroup(); oldRom.BaseStream.Seek(currentAGroup.setPointer, SeekOrigin.Begin); currentDGroup.setData = (byte)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.enemyPointer, SeekOrigin.Begin); currentDGroup.enemyData = (ushort)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.objectPointer, SeekOrigin.Begin); currentDGroup.objectData = (ushort)oldRom.ReadUInt32(); if (levelFlags[flag++] == true) { castleAddressGroups.Add(currentAGroup); castleDataGroups.Add(currentDGroup); } } castleAddressReader.Close(); mt.Shuffle(castleDataGroups); // Combine all address and data groups List <AddressGroup> allAddressGroups = regAddressGroups; allAddressGroups.AddRange(fortAddressGroups); allAddressGroups.AddRange(castleAddressGroups); List <DataGroup> allDataGroups = regDataGroups; allDataGroups.AddRange(fortDataGroups); allDataGroups.AddRange(castleDataGroups); // New ROM = copy of old ROM with offsets at level pointers shuffled oldRom.BaseStream.Seek(0, SeekOrigin.Begin); BinaryWriter newRom = new BinaryWriter(File.OpenWrite(newRomPath)); oldRom.BaseStream.CopyTo(newRom.BaseStream); newRom.Flush(); for (int level = 0; level < allAddressGroups.Count; ++level) { // Set data offset is 4 bits wide and located in the lower nibble only -- Don't overwrite the upper nibble! oldRom.BaseStream.Seek(allAddressGroups[level].setPointer, SeekOrigin.Begin); newRom.BaseStream.Seek(allAddressGroups[level].setPointer, SeekOrigin.Begin); byte newSetByte = oldRom.ReadByte(); newSetByte |= (byte)(allDataGroups[level].setData & 0x0f); newSetByte &= (byte)(allDataGroups[level].setData | 0xf0); newRom.Write(newSetByte); // Enemy data offset is 16 bits wide newRom.BaseStream.Seek(allAddressGroups[level].enemyPointer, SeekOrigin.Begin); newRom.Write(allDataGroups[level].enemyData); // Object data offset is 16 bits wide newRom.BaseStream.Seek(allAddressGroups[level].objectPointer, SeekOrigin.Begin); newRom.Write(allDataGroups[level].objectData); } oldRom.Close(); newRom.Close(); return(newRomPath); }
public string CreateRom() { int flag = 0; // Get all the necessary level pointer ROM addresses and data location offsets for regular levels BinaryReader oldRom = new BinaryReader(File.OpenRead(oldRomPath)); BinaryReader regAddressReader = new BinaryReader(File.OpenRead("regular.dat")); List<AddressGroup> regAddressGroups = new List<AddressGroup>(); List<DataGroup> regDataGroups = new List<DataGroup>(); while (regAddressReader.BaseStream.Position != regAddressReader.BaseStream.Length) { AddressGroup currentAGroup = new AddressGroup(); currentAGroup.setPointer = regAddressReader.ReadUInt32(); currentAGroup.enemyPointer = regAddressReader.ReadUInt32(); currentAGroup.objectPointer = regAddressReader.ReadUInt32(); DataGroup currentDGroup = new DataGroup(); oldRom.BaseStream.Seek(currentAGroup.setPointer, SeekOrigin.Begin); currentDGroup.setData = (byte)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.enemyPointer, SeekOrigin.Begin); currentDGroup.enemyData = (ushort)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.objectPointer, SeekOrigin.Begin); currentDGroup.objectData = (ushort)oldRom.ReadUInt32(); if (levelFlags[flag++] == true) { regAddressGroups.Add(currentAGroup); regDataGroups.Add(currentDGroup); } } regAddressReader.Close(); mt.Shuffle(regDataGroups); // Repeat above for fortresses BinaryReader fortAddressReader = new BinaryReader(File.OpenRead("fort.dat")); List<AddressGroup> fortAddressGroups = new List<AddressGroup>(); List<DataGroup> fortDataGroups = new List<DataGroup>(); while (fortAddressReader.BaseStream.Position != fortAddressReader.BaseStream.Length) { AddressGroup currentAGroup = new AddressGroup(); currentAGroup.setPointer = fortAddressReader.ReadUInt32(); currentAGroup.enemyPointer = fortAddressReader.ReadUInt32(); currentAGroup.objectPointer = fortAddressReader.ReadUInt32(); DataGroup currentDGroup = new DataGroup(); oldRom.BaseStream.Seek(currentAGroup.setPointer, SeekOrigin.Begin); currentDGroup.setData = (byte)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.enemyPointer, SeekOrigin.Begin); currentDGroup.enemyData = (ushort)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.objectPointer, SeekOrigin.Begin); currentDGroup.objectData = (ushort)oldRom.ReadUInt32(); if (levelFlags[flag++] == true) { fortAddressGroups.Add(currentAGroup); fortDataGroups.Add(currentDGroup); } } fortAddressReader.Close(); mt.Shuffle(fortDataGroups); // Repeat above for castles BinaryReader castleAddressReader = new BinaryReader(File.OpenRead("castle.dat")); List<AddressGroup> castleAddressGroups = new List<AddressGroup>(); List<DataGroup> castleDataGroups = new List<DataGroup>(); while (castleAddressReader.BaseStream.Position != castleAddressReader.BaseStream.Length) { AddressGroup currentAGroup = new AddressGroup(); currentAGroup.setPointer = castleAddressReader.ReadUInt32(); currentAGroup.enemyPointer = castleAddressReader.ReadUInt32(); currentAGroup.objectPointer = castleAddressReader.ReadUInt32(); DataGroup currentDGroup = new DataGroup(); oldRom.BaseStream.Seek(currentAGroup.setPointer, SeekOrigin.Begin); currentDGroup.setData = (byte)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.enemyPointer, SeekOrigin.Begin); currentDGroup.enemyData = (ushort)oldRom.ReadUInt32(); oldRom.BaseStream.Seek(currentAGroup.objectPointer, SeekOrigin.Begin); currentDGroup.objectData = (ushort)oldRom.ReadUInt32(); if (levelFlags[flag++] == true) { castleAddressGroups.Add(currentAGroup); castleDataGroups.Add(currentDGroup); } } castleAddressReader.Close(); mt.Shuffle(castleDataGroups); // Combine all address and data groups List<AddressGroup> allAddressGroups = regAddressGroups; allAddressGroups.AddRange(fortAddressGroups); allAddressGroups.AddRange(castleAddressGroups); List<DataGroup> allDataGroups = regDataGroups; allDataGroups.AddRange(fortDataGroups); allDataGroups.AddRange(castleDataGroups); // New ROM = copy of old ROM with offsets at level pointers shuffled oldRom.BaseStream.Seek(0, SeekOrigin.Begin); BinaryWriter newRom = new BinaryWriter(File.OpenWrite(newRomPath)); oldRom.BaseStream.CopyTo(newRom.BaseStream); newRom.Flush(); for (int level = 0; level < allAddressGroups.Count; ++level) { // Set data offset is 4 bits wide and located in the lower nibble only -- Don't overwrite the upper nibble! oldRom.BaseStream.Seek(allAddressGroups[level].setPointer, SeekOrigin.Begin); newRom.BaseStream.Seek(allAddressGroups[level].setPointer, SeekOrigin.Begin); byte newSetByte = oldRom.ReadByte(); newSetByte |= (byte)(allDataGroups[level].setData & 0x0f); newSetByte &= (byte)(allDataGroups[level].setData | 0xf0); newRom.Write(newSetByte); // Enemy data offset is 16 bits wide newRom.BaseStream.Seek(allAddressGroups[level].enemyPointer, SeekOrigin.Begin); newRom.Write(allDataGroups[level].enemyData); // Object data offset is 16 bits wide newRom.BaseStream.Seek(allAddressGroups[level].objectPointer, SeekOrigin.Begin); newRom.Write(allDataGroups[level].objectData); } oldRom.Close(); newRom.Close(); return newRomPath; }