Пример #1
0
        /// <summary>
        /// 给ROM打IPS补丁
        /// </summary>
        /// <param name="IPSFileName">IPS补丁文件名</param>
        /// <param name="ROMFileName">ROM文件名</param>
        public static void ApplyPatchToROM(string IPSFileName, string ROMFileName)
        {
            IPSInfo info = LoadIPS(IPSFileName);

            if (info == null)
            {
                return;
            }
            FileStream fs = new FileStream(ROMFileName, FileMode.Open);

            if (fs != null)
            {
                BinaryWriter bw = new BinaryWriter(fs);
                if (bw != null)
                {
                    foreach (RecordInfo ri in info.records)
                    {
                        bw.Seek(ri.offset, SeekOrigin.Begin);
                        if (ri.isRLE)
                        {
                            for (int i = 0; i < ri.len; ++i)
                            {
                                bw.Write(ri.data);
                            }
                        }
                        else
                        {
                            bw.Write(ri.data);
                        }
                    }
                    bw.Flush();
                    bw.Close();
                    bw.Dispose();
                    bw = null;
                }
                fs.Close();
                fs.Dispose();
                fs = null;
            }
        }
Пример #2
0
        /// <summary>
        /// 载入IPS补丁,获得补丁信息
        /// </summary>
        /// <param name="IPSFileName">IPS补丁文件名</param>
        /// <returns>补丁信息</returns>
        public static IPSInfo LoadIPS(string IPSFileName)
        {
            IPSInfo    info = null;
            FileStream fs   = new FileStream(IPSFileName, FileMode.Open);

            if (fs != null)
            {
                BinaryReader br = new BinaryReader(fs);
                if (br != null)
                {
                    info = new IPSInfo();
                    // 先读5字节的patch
                    Byte[] patch = br.ReadBytes(5);
                    if (patch[0] != 'P' || patch[1] != 'A' || patch[1] != 'T' || patch[1] != 'C' || patch[1] != 'H')
                    {
                        info = null;
                    }
                    if (info != null)
                    {
                        info.records = new List <RecordInfo>();
                        // 循环读取记录,直到读到eof为止
                        while (true)
                        {
                            RecordInfo ri = new RecordInfo();
                            // 先读3字节
                            Byte[] data = br.ReadBytes(3);
                            // 检测是否读到了eof,是的话就跳出循环
                            if (data[0] == 'E' && data[1] == 'O' && data[2] == 'F')
                            {
                                break;
                            }
                            // 3字节的offset
                            ri.offset = ((int)data[0] << 16) | ((int)data[1] << 8) | ((int)data[2] << 0);
                            // 再读2字节
                            data = br.ReadBytes(2);
                            // 检测是否是00 00。如果是的话则证明是RLE记录
                            if (data[0] == 0 && data[1] == 0)
                            {
                                ri.isRLE = true;
                                // 再读2字节作为len
                                data   = br.ReadBytes(2);
                                ri.len = (short)(((short)data[0] << 8) | ((short)data[1] << 0));
                                // 再读1字节作为RLE数据
                                ri.data = br.ReadBytes(1);
                            }
                            // 不是RLE记录
                            else
                            {
                                ri.isRLE = false;
                                // 2字节的len
                                ri.len = (short)(((short)data[0] << 8) | ((short)data[1] << 0));
                                // 再读len字节作为数据
                                ri.data = br.ReadBytes(ri.len);
                            }
                            info.records.Add(ri);
                        }
                        //// 如果此时已经读完了IPS文件,则无truncate,否则再读3字节作为truncateOffset
                        //if (br.BaseStream.Position >= br.BaseStream.Length)
                        //{
                        //    info.truncateOffset = 0;
                        //}
                        //else
                        //{
                        //    Byte[] data = br.ReadBytes(3);
                        //    info.truncateOffset = ((int)data[0] << 16) | ((int)data[1] << 8) | ((int)data[2] << 0);
                        //}
                    }
                    br.Close();
                    br.Dispose();
                    br = null;
                }
                fs.Close();
                fs.Dispose();
                fs = null;
            }
            return(info);
        }
Пример #3
0
        /// <summary>
        /// 给ROM打补丁,并生成IPS文件
        /// </summary>
        /// <param name="fileName">ROM文件名</param>
        /// <param name="prgData">PRG补丁数据。如果为null的话则PRG无需打补丁</param>
        /// <param name="chrData">CHR补丁数据。如果为null的话则CHR无需打补丁</param>
        /// <param name="IPSFileName">IPS补丁文件名</param>
        public static void CreateIPS(string fileName, Byte[] prgData, Byte[] chrData, string IPSFileName)
        {
            // 获得原始ROM数据
            Byte[]     romData = null;
            FileStream fs      = new FileStream(fileName, FileMode.Open);

            if (fs != null)
            {
                BinaryReader br = new BinaryReader(fs);
                if (br != null)
                {
                    romData = br.ReadBytes((int)fs.Length);
                    br.Close();
                    br.Dispose();
                    br = null;
                }
                fs.Close();
                fs.Dispose();
                fs = null;
            }
            if (prgData == null)
            {
                prgData = GetPRGData(fileName);
            }
            if (chrData == null)
            {
                chrData = GetCHRData(fileName);
            }
            // 获得新ROM数据
            Byte[] newROMData = new Byte[romData.Length];
            for (int i = 0; i < 16; ++i)
            {
                newROMData[0 + i] = romData[i];
            }
            for (int i = 0; i < prgData.Length; ++i)
            {
                newROMData[16 + i] = prgData[i];
            }
            for (int i = 0; i < chrData.Length; ++i)
            {
                newROMData[16 + prgData.Length + i] = chrData[i];
            }
            // 差异对比
            IPSInfo info = new IPSInfo();

            info.patch   = new char[] { 'P', 'A', 'T', 'C', 'H' };
            info.records = new List <RecordInfo>();
            int offset = 0;

            while (offset < Math.Min(romData.Length, newROMData.Length))
            {
                if (romData[offset] != newROMData[offset])
                {
                    RecordInfo ri           = new RecordInfo();
                    short      RLERecordLen = getRLERecord(newROMData, offset);
                    if (RLERecordLen > 1)
                    {
                        ri.isRLE = true;
                        ri.len   = RLERecordLen;
                        ri.data  = new Byte[] { newROMData[offset] };
                        offset  += RLERecordLen;
                    }
                    else
                    {
                        ri.isRLE = false;
                        ri.data  = getRecord(romData, newROMData, offset);
                        ri.len   = (short)ri.data.Length;
                        offset  += ri.len;
                    }
                    info.records.Add(ri);
                }
            }
            if (newROMData.Length > romData.Length)
            {
                RecordInfo ri = new RecordInfo();
                ri.isRLE = false;
                ri.len   = (short)(newROMData.Length - romData.Length);
                ri.data  = new Byte[ri.len];
                for (int i = 0; i < ri.data.Length; ++i)
                {
                    ri.data[i] = newROMData[romData.Length + i];
                }
                info.records.Add(ri);
            }
            else if (newROMData.Length < romData.Length)
            {
                Console.WriteLine("暂不支持truncate!");
            }
            info.eof = new char[] { 'E', 'O', 'F' };
            // 写IPS文件
            fs = new FileStream(IPSFileName, FileMode.Create);
            if (fs != null)
            {
                BinaryWriter bw = new BinaryWriter(fs);
                if (bw != null)
                {
                    bw.Write(info.patch);
                    foreach (RecordInfo ri in info.records)
                    {
                        bw.Write((Byte)((ri.offset >> 16) & 0xFF));
                        bw.Write((Byte)((ri.offset >> 8) & 0xFF));
                        bw.Write((Byte)((ri.offset >> 0) & 0xFF));
                        if (ri.isRLE)
                        {
                            bw.Write((Byte)0);
                            bw.Write((Byte)0);
                        }
                        bw.Write((Byte)((ri.len >> 8) & 0xFF));
                        bw.Write((Byte)((ri.len >> 0) & 0xFF));
                        foreach (Byte b in ri.data)
                        {
                            bw.Write(b);
                        }
                    }
                    bw.Write(info.eof);

                    bw.Flush();
                    bw.Close();
                    bw.Dispose();
                    bw = null;
                }
                fs.Close();
                fs.Dispose();
                fs = null;
            }
        }