Example #1
0
        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);
        }
Example #2
0
        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;
        }