Пример #1
0
    private static void PostProcess(Data data)
    {
        Pad(data);

        var snesApi = data.GetSnesApi();

        Debug.Assert(snesApi != null);

        // inject the game name into the bytes
        // This is a UTF8 string that needs to be converted to ShiftJIS (Ascii w/some japanese chars) encoding.
        snesApi.SetCartridgeTitle(GetSampleUtf8CartridgeTitle());

        // initialize some SNES header stuff (this is not complete, feel free to add things that are useful)
        Debug.Assert(snesApi.RomMapMode == RomMapMode.LoRom);
        Debug.Assert(snesApi.RomSpeed == RomSpeed.FastRom);
        var       romSettingsOffset = RomUtil.GetRomSettingOffset(RomMapMode.LoRom);
        const int loromAndFastRom   = 0x30;

        data.RomBytes[romSettingsOffset].Rom = loromAndFastRom;

        // do this LAST after all modifications to the ROM bytes have been completed
        snesApi.FixChecksum();

        // NORMALLY when a project is loaded, we have to open the ROM file on disk and read the bytes on disk into RomBytes
        // for this sample data, there is no ROM on disk, so we tell Diz we already took care of it
        data.RomBytesLoaded = true;
    }
 public void TestRomDetectionGeneratedRom()
 {
     sampleDataFixture.Should().NotBeNull();
     var detectRomMapMode = RomUtil.DetectRomMapMode(sampleDataFixture.SampleRomBytes, out var detectedValidRomMapType);
     detectedValidRomMapType.Should().Be(true);
     detectRomMapMode.Should().Be(RomMapMode.LoRom);
 }
Пример #3
0
        public static void ConvertSnesToPcLoRom()
        {
            var romSize = RomUtil.GetBankSize(RomMapMode.LoRom) * 8;

            Assert.Equal(-1, RomUtil.ConvertSnesToPc(0x790000, RomMapMode.LoRom, romSize));
            Assert.Equal(0x00, RomUtil.ConvertSnesToPc(0x808000, RomMapMode.LoRom, romSize));
        }
 public void TestRomDetectionHiRom()
 {
     var detectRomMapMode = RomUtil.DetectRomMapMode(
         fileReader.ReadRomFileBytes(CartNameData.ExampleHiRomFile), 
         out var detectedValidRomMapType);
     
     detectedValidRomMapType.Should().Be(true);
     detectRomMapMode.Should().Be(RomMapMode.HiRom);
 }
Пример #5
0
        public static void ConvertSnesToPcHiRom()
        {
            var romSize = RomUtil.GetBankSize(RomMapMode.HiRom) * 64;

            Assert.Equal(-1, RomUtil.ConvertSnesToPc(0x202000, RomMapMode.HiRom, romSize));
            Assert.Equal(0x01FFFF, RomUtil.ConvertSnesToPc(0x41FFFF, RomMapMode.HiRom, romSize));
            Assert.Equal(0x000123, RomUtil.ConvertSnesToPc(0xC00123, RomMapMode.HiRom, romSize));
            Assert.Equal(0x3F0123, RomUtil.ConvertSnesToPc(0xFF0123, RomMapMode.HiRom, romSize));
            Assert.Equal(-1, RomUtil.ConvertSnesToPc(0x10000000, RomMapMode.HiRom, romSize));
        }
Пример #6
0
    public int FixMisalignedFlags()
    {
        int count = 0, size = GetRomSize();

        for (var i = 0; i < size; i++)
        {
            var flag = GetFlag(i);

            switch (flag)
            {
            case FlagType.Opcode:
            {
                int len = GetInstructionLength(i);
                for (var j = 1; j < len && i + j < size; j++)
                {
                    if (GetFlag(i + j) != FlagType.Operand)
                    {
                        SetFlag(i + j, FlagType.Operand);
                        count++;
                    }
                }
                i += len - 1;
                break;
            }

            case FlagType.Operand:
                SetFlag(i, FlagType.Opcode);
                count++;
                i--;
                break;

            default:
            {
                if (RomUtil.GetByteLengthForFlag(flag) > 1)
                {
                    int step = RomUtil.GetByteLengthForFlag(flag);
                    for (int j = 1; j < step; j++)
                    {
                        if (GetFlag(i + j) == flag)
                        {
                            continue;
                        }
                        SetFlag(i + j, flag);
                        count++;
                    }
                    i += step - 1;
                }

                break;
            }
            }
        }

        return(count);
    }
Пример #7
0
        public Dictionary <int, Data.FlagType> GenerateHeaderFlags()
        {
            var flags = new Dictionary <int, Data.FlagType>();

            if (ShouldCheckHeader)
            {
                RomUtil.GenerateHeaderFlags(RomSettingsOffset, flags, ImportSettings.RomBytes);
            }

            return(flags);
        }
Пример #8
0
        protected virtual void Init()
        {
            InitOutput();
            SetupParseList();

            BankSize        = RomUtil.GetBankSize(Data.RomMapMode);
            ErrorCount      = 0;
            LabelsWeVisited = new List <int>();

            GenerateAdditionalExtraLabels();
            WriteGeneratedLabelsIntoUnderlyingData(); // MODIFIES DATA. MAKE SURE TO UNDO THIS.
        }
Пример #9
0
        private static bool MatchCartTitle(RomToProjectAssociation container, Project?project,
                                           ValidationContext <RomToProjectAssociation> validationContext)
        {
            if (project?.Data == null)
            {
                return(false);
            }

            var gameNameFromRomBytes  = RomUtil.GetCartridgeTitleFromRom(container.RomBytes, project.Data.RomSettingsOffset);
            var requiredGameNameMatch = project.InternalRomGameName;

            return(MatchCartTitle(requiredGameNameMatch, gameNameFromRomBytes, validationContext));
        }
Пример #10
0
        public static void TestTitleRead()
        {
            var fakeRom = Enumerable
                          .Range(0, 0x7FC0)
                          .Select(_ => (byte)0x00)
                          .Concat(RawRomBytes)
                          .ToArray();

            RomUtil
            .GetCartridgeTitleFromRom(
                fakeRom,
                RomUtil.GetRomSettingOffset(RomMapMode.LoRom)
                ).Should().Be(ExpectedTitleStr);
        }
Пример #11
0
        private void Mark(int offset)
        {
            if (!RomDataPresent())
            {
                return;
            }

            ProjectController.MarkChanged();
            var newOffset = Project.Data.MarkTypeFlag(offset, markFlag, RomUtil.GetByteLengthForFlag(markFlag));

            SelectOffset(newOffset);

            UpdateUI_Tmp3();
        }
Пример #12
0
    private void Mark(int offset)
    {
        if (!RomDataPresent())
        {
            return;
        }

        ProjectController.MarkChanged();
        var newOffset = Project.Data.GetSnesApi().MarkTypeFlag(offset, markFlag, RomUtil.GetByteLengthForFlag(markFlag));

        SelectOffset(newOffset, new ISnesNavigation.HistoryArgs {
            Description = "Mark (single)"
        });

        UpdateUi_TimerAndPercent();
    }
Пример #13
0
        public void CreateSettingsFromRom(string filename)
        {
            var romBytes = RomUtil.ReadAllRomBytesFromFile(filename);

            ImportSettings = new ImportRomSettings
            {
                RomFilename = filename,
                RomBytes    = romBytes,
                RomMapMode  = RomUtil.DetectRomMapMode(romBytes, out var detectedMapModeSuccess)
            };

            if (detectedMapModeSuccess)
            {
                DetectedMapMode = ImportSettings.RomMapMode;
            }

            OnSettingsCreated();
        }
Пример #14
0
        // Mark collected trace data for a RomByte (which should be an opcode) AND any of the operands that follow us.
        private void SetOpcodeAndOperandsFromTraceData(
            int snesAddress, int dataBank, int directPage,
            bool xflagSet, bool mflagSet,
            int opcodeLen = -1)
        {
            // extremely performance-intensive function. be really careful when adding stuff
            var currentIndex = 0;

            while (true)
            {
                if (!SetOneRomByteFromTraceData(snesAddress, dataBank, directPage, xflagSet, mflagSet, opcodeLen, currentIndex))
                {
                    break;
                }

                snesAddress = RomUtil.CalculateSnesOffsetWithWrap(snesAddress, 1);
                currentIndex++;
            }
        }
 private static int GetNextSNESAddress(int modDataSnesAddress)
 {
     return(RomUtil.CalculateSnesOffsetWithWrap(modDataSnesAddress, 1));
 }
Пример #16
0
        private void buttonScan_Click(object sender, EventArgs e)
        {
            textLog.Text = "";
            int found = 0, offset = 0;

            while (found < 500 && offset < Data.GetRomSize())
            {
                FlagType flag = Data.GetFlag(offset), check = flag == FlagType.Opcode ? FlagType.Operand : flag;
                var      step = flag == FlagType.Opcode ? Data.GetInstructionLength(offset) : RomUtil.GetByteLengthForFlag(flag);

                if (flag == FlagType.Operand)
                {
                    found++;
                    textLog.Text +=
                        $"{Util.NumberToBaseString(Data.ConvertPCtoSnes(offset), Util.NumberBase.Hexadecimal, 6, true)} (0x{Util.NumberToBaseString(offset, Util.NumberBase.Hexadecimal, 0)}): Operand without Opcode\r\n";
                }
                else if (step > 1)
                {
                    for (var i = 1; i < step; i++)
                    {
                        if (Data.GetFlag(offset + i) == check)
                        {
                            continue;
                        }
                        found++;
                        textLog.Text +=
                            $"{Util.NumberToBaseString(Data.ConvertPCtoSnes(offset + i), Util.NumberBase.Hexadecimal, 6, true)} (0x{Util.NumberToBaseString(offset + i, Util.NumberBase.Hexadecimal, 0)}): {Util.GetEnumDescription(Data.GetFlag(offset + i))} is not {Util.GetEnumDescription(check)}\r\n";
                    }
                }

                offset += step;
            }

            if (found == 0)
            {
                textLog.Text = "No misaligned flags found!";
            }
        }
Пример #17
0
        private int GetByteLengthFollowing(int offset)
        {
            var flag = Data.GetFlag(offset);

            return(flag == Data.FlagType.Opcode ? GetLineByteLength(offset) : RomUtil.GetByteLengthForFlag(flag));
        }
Пример #18
0
        public override (Project project, string warning) Load(byte[] data)
        {
            if (!IsBinaryFileFormat(data))
            {
                throw new InvalidDataException($"This is not a binary serialized project file!");
            }

            byte version = data[0];

            ValidateProjectFileVersion(version);

            var project = new Project
            {
                Data = new Data()
            };

            // version 0 needs to convert PC to SNES for some addresses
            ByteUtil.AddressConverter converter = address => address;
            if (version == 0)
            {
                converter = project.Data.ConvertPCtoSnes;
            }

            // read mode, speed, size
            project.Data.RomMapMode = (RomMapMode)data[HeaderSize];
            project.Data.RomSpeed   = (RomSpeed)data[HeaderSize + 1];
            var size = ByteUtil.ByteArrayToInt32(data, HeaderSize + 2);

            // read internal title
            var pointer = HeaderSize + 6;

            project.InternalRomGameName = RomUtil.ReadStringFromByteArray(data, RomUtil.LengthOfTitleName, pointer);
            pointer += RomUtil.LengthOfTitleName;

            // read checksums
            project.InternalCheckSum = ByteUtil.ByteArrayToInt32(data, pointer);
            pointer += 4;

            // read full filepath to the ROM .sfc file
            while (data[pointer] != 0)
            {
                project.AttachedRomFilename += (char)data[pointer++];
            }
            pointer++;

            project.Data.RomBytes.Create(size);

            for (int i = 0; i < size; i++)
            {
                project.Data.SetDataBank(i, data[pointer + i]);
            }
            pointer++;
            for (int i = 0; i < size; i++)
            {
                project.Data.SetDirectPage(i, data[pointer + size + i] | (data[pointer + 1 * size + i] << 8));
            }
            pointer += 2;
            for (int i = 0; i < size; i++)
            {
                project.Data.SetXFlag(i, data[pointer * size + i] != 0);
            }
            pointer++;
            for (int i = 0; i < size; i++)
            {
                project.Data.SetMFlag(i, data[pointer * size + i] != 0);
            }
            pointer++;
            for (int i = 0; i < size; i++)
            {
                project.Data.SetFlag(i, (Data.FlagType)data[pointer * size + i]);
            }
            pointer++;
            for (int i = 0; i < size; i++)
            {
                project.Data.SetArchitecture(i, (Data.Architecture)data[pointer * size + i]);
            }
            pointer++;
            for (int i = 0; i < size; i++)
            {
                project.Data.SetInOutPoint(i, (Data.InOutPoint)data[pointer * size + i]);
            }
            pointer++;
            //for (int i = 0; i < size; i++) project.Data.SetBaseAddr(i, (Data.InOutPoint)data[pointer * size + i]); pointer++;

            ReadLabels(project, data, ref pointer, converter, version >= 2);
            ReadComments(project, data, ref pointer, converter);

            project.UnsavedChanges = false;

            var warning = "";

            if (version != LatestFileFormatVersion)
            {
                warning = "This project file is in an older format.\n" +
                          "You may want to back up your work or 'Save As' in case the conversion goes wrong.\n" +
                          "The project file will be untouched until it is saved again.";
            }

            return(project, warning);
        }
Пример #19
0
        public static Data PopulateFromRom(this Data data, ByteSource romByteSource, RomMapMode romMapMode, RomSpeed romSpeed)
        {
            var mapping = RomUtil.CreateRomMappingFromRomByteSource(romByteSource, romMapMode, romSpeed);

            return(PopulateFrom(data, mapping));
        }
Пример #20
0
 public int ConvertSnesToPc(int address) =>
 RomUtil.ConvertSnesToPc(address, Data.RomMapMode, GetRomSize());
Пример #21
0
        private void RegenerateSampleOutput()
        {
            var result = RomUtil.GetSampleAssemblyOutput(settings);

            textSample.Text = result.OutputStr;
        }
 private int ConvertSnesToPc(int modDataSnesAddress)
 {
     // PERF: could use Data.ConvertSnesToPc(), but, by caching the two variables here,
     // we can save some locking and maybe speed things up.
     return(RomUtil.ConvertSnesToPc(modDataSnesAddress, romMapModeCached, romSizeCached));
 }
Пример #23
0
        private void table_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
        {
            var row = e.RowIndex + ViewOffset;

            if (row >= Project.Data.GetRomSize())
            {
                return;
            }
            switch (e.ColumnIndex)
            {
            case 0:
                e.Value = Project.Data.Labels.GetLabelName(Project.Data.ConvertPCtoSnes(row));
                break;

            case 1:
                e.Value = Util.NumberToBaseString(Project.Data.ConvertPCtoSnes(row), Util.NumberBase.Hexadecimal, 6);
                break;

            case 2:
                e.Value = (char)Project.Data.GetRomByte(row);
                break;

            case 3:
                e.Value = Util.NumberToBaseString(Project.Data.GetRomByte(row) ?? 0x0, displayBase);
                break;

            case 4:
                e.Value = RomUtil.PointToString(Project.Data.GetSnesApi().GetInOutPoint(row));
                break;

            case 5:
                var len = Project.Data.GetSnesApi().GetInstructionLength(row);
                e.Value = row + len <= Project.Data.GetRomSize() ? Project.Data.GetSnesApi().GetInstruction(row) : "";
                break;

            case 6:
                var ia = Project.Data.GetSnesApi().GetIntermediateAddressOrPointer(row);
                e.Value = ia >= 0 ? Util.NumberToBaseString(ia, Util.NumberBase.Hexadecimal, 6) : "";
                break;

            case 7:
                e.Value = Util.GetEnumDescription(Project.Data.GetSnesApi().GetFlag(row));
                break;

            case 8:
                e.Value = Util.NumberToBaseString(Project.Data.GetSnesApi().GetDataBank(row), Util.NumberBase.Hexadecimal, 2);
                break;

            case 9:
                e.Value = Util.NumberToBaseString(Project.Data.GetSnesApi().GetDirectPage(row), Util.NumberBase.Hexadecimal, 4);
                break;

            case 10:
                e.Value = RomUtil.BoolToSize(Project.Data.GetSnesApi().GetMFlag(row));
                break;

            case 11:
                e.Value = RomUtil.BoolToSize(Project.Data.GetSnesApi().GetXFlag(row));
                break;

            case 12:
                e.Value = Project.Data.GetCommentText(Project.Data.ConvertPCtoSnes(row));
                break;
            }
        }
Пример #24
0
 public int ConvertPCtoSnes(int offset)
 {
     return(RomUtil.ConvertPCtoSnes(offset, RomMapMode, RomSpeed));
 }
Пример #25
0
 public int ConvertPCtoSnes(int offset) =>
 RomUtil.ConvertPCtoSnes(offset, Data.RomMapMode, Data.RomSpeed);
Пример #26
0
        public static Data PopulateFrom(this Data data, IReadOnlyCollection <byte> actualRomBytes, RomMapMode romMapMode, RomSpeed romSpeed)
        {
            var mapping = RomUtil.CreateRomMappingFromRomRawBytes(actualRomBytes, romMapMode, romSpeed);

            return(PopulateFrom(data, mapping));
        }
Пример #27
0
 private Dictionary <int, Label> GenerateVectorLabels() =>
 RomUtil.GenerateVectorLabels(
     VectorTableEntriesEnabled, RomSettingsOffset, ImportSettings.RomBytes, ImportSettings.RomMapMode);
Пример #28
0
 public int GetBankSize() =>
 RomUtil.GetBankSize(Data.RomMapMode);
Пример #29
0
 public int GetBankSize()
 {
     return(RomUtil.GetBankSize(RomMapMode));
 }
Пример #30
0
        public void PaintCell(int offset, DataGridViewCellStyle style, int column_index, int selOffset, DataGridViewCellPaintingEventArgs cell)
        {
            // editable cells show up green
            string column = ColumnName(column_index);

            if (column == "label" || column == "base" || column == "db" || column == "dp" || column == "ia" || column == "comment")
            {
                style.SelectionBackColor = Color.Chartreuse;
            }

            bool diff = Project.Data.GetLabelName(Project.Data.ConvertPCtoSnes(offset)) == "" && (offset > 0 && Project.Data.GetFlag(offset - 1) == Project.Data.GetFlag(offset));

            Data.InOutPoint   point    = Project.Data.GetInOutPoint(offset);
            Data.FlagType     flag     = Project.Data.GetFlag(offset);
            Data.ConstantType constant = Project.Data.GetConstantType(offset);
            switch (flag)
            {
            case Data.FlagType.Unreached:
                style.BackColor = Color.LightGray;
                style.ForeColor = Color.DarkSlateGray;
                break;

            case Data.FlagType.Opcode:
                int opcode = Project.Data.GetRomByte(offset);
                switch (column)
                {
                case "points":
                    int r = 255, g = 255, b = 255;
                    if ((point & (Data.InOutPoint.EndPoint | Data.InOutPoint.OutPoint)) != 0)
                    {
                        g -= 50;
                    }
                    if ((point & (Data.InOutPoint.InPoint)) != 0)
                    {
                        r -= 50;
                    }
                    if ((point & (Data.InOutPoint.ReadPoint)) != 0)
                    {
                        b -= 50;
                    }
                    style.BackColor = Color.FromArgb(r, g, b);
                    break;

                case "instruction":
                    if (opcode == 0x40 || opcode == 0xCB || opcode == 0xDB || opcode == 0xF8 ||      // RTI WAI STP SED
                        opcode == 0xFB || opcode == 0x00 || opcode == 0x02 || opcode == 0x42            // XCE BRK COP WDM
                        )
                    {
                        style.BackColor = Color.Yellow;
                    }
                    if (constant != Data.ConstantType.Hexadecimal)
                    {
                        style.BackColor = Color.FromArgb(50 - (int)constant, 100 - (int)constant, 255 - ((int)constant * 20));
                        style.ForeColor = Color.White;
                    }
                    break;

                case "db":
                    if (opcode == 0xAB || opcode == 0x44 || opcode == 0x54)         // PLB MVP MVN
                    {
                        style.BackColor = Color.OrangeRed;
                    }
                    else if (opcode == 0x8B)         // PHB
                    {
                        style.BackColor = Color.Yellow;
                    }
                    break;

                case "dp":
                    if (opcode == 0x2B || opcode == 0x5B)         // PLD TCD
                    {
                        style.BackColor = Color.OrangeRed;
                    }
                    if (opcode == 0x0B || opcode == 0x7B)         // PHD TDC
                    {
                        style.BackColor = Color.Yellow;
                    }
                    break;

                case "m":
                case "x":
                    int mask = column == "m" ? 0x20 : 0x10;
                    if (opcode == 0x28 || ((opcode == 0xC2 || opcode == 0xE2) &&      // PLP SEP REP
                                           (Project.Data.GetRomByte(offset + 1) & mask) != 0)) // relevant bit set
                    {
                        style.BackColor = Color.OrangeRed;
                    }
                    if (opcode == 0x08)         // PHP
                    {
                        style.BackColor = Color.Yellow;
                    }
                    break;
                }
                switch (opcode)
                {
                case 0x4C:
                case 0x5C:
                case 0x6C:
                case 0x7C:
                case 0xDC:
                    style.BackColor = Color.WhiteSmoke;
                    break;

                case 0x60:
                case 0x6B:
                    style.BackColor = Color.LightGreen;
                    break;
                }
                break;

            case Data.FlagType.Operand:
                style.ForeColor = Color.LightGray;
                break;

            case Data.FlagType.Graphics:
                style.BackColor = Color.LightPink;
                break;

            case Data.FlagType.Music:
                style.BackColor = Color.PowderBlue;
                break;

            case Data.FlagType.Data8Bit:
            case Data.FlagType.Data16Bit:
            case Data.FlagType.Data24Bit:
            case Data.FlagType.Data32Bit:
                style.BackColor = Color.NavajoWhite;
                if (column == "ia" && Project.Data.GetConstantType(offset) == Data.ConstantType.Color && (point & Data.InOutPoint.ReadPoint) > 0)
                {
                    if (flag == Data.FlagType.Data16Bit)
                    {
                        style.BackColor = Util.ColorRGB555(Project.Data.GetRomWord(offset));
                    }
                    else if (flag == Data.FlagType.Data24Bit)
                    {
                        style.BackColor = Color.FromArgb(Project.Data.GetRomByte(offset + 2), Project.Data.GetRomByte(offset + 1), Project.Data.GetRomByte(offset));
                    }
                }
                if (RomUtil.GetByteLengthForFlag(flag) > 1 && (point & Data.InOutPoint.ReadPoint) == 0)
                {
                    style.ForeColor = Color.DarkGray;
                }
                break;

            case Data.FlagType.Pointer16Bit:
            case Data.FlagType.Pointer24Bit:
            case Data.FlagType.Pointer32Bit:
                style.BackColor = Color.Orchid;
                if ((point & (Data.InOutPoint.ReadPoint | Data.InOutPoint.EndPoint)) == 0)
                {
                    style.ForeColor = Color.DarkMagenta;
                }
                break;

            case Data.FlagType.Text:
                style.BackColor = Color.Aquamarine;
                if (diff)
                {
                    style.ForeColor = Color.DarkGray;
                }
                break;

            case Data.FlagType.Empty:
                style.BackColor = Color.DarkSlateGray;
                style.ForeColor = Color.LightGray;
                break;

            case Data.FlagType.Binary:
                style.BackColor = Color.Aqua;
                break;
            }

            int ia  = Project.Data.ConvertSnesToPc(Project.Data.GetIntermediateAddressOrPointer(offset));
            int sia = Project.Data.ConvertSnesToPc(Project.Data.GetIntermediateAddressOrPointer(selOffset));

            if (selOffset >= 0 && selOffset < Project.Data.GetRomSize())
            {
                if ((column == "pc" && sia >= 0 && sia == offset) || (column == "ia" && ia >= 0 && ia == selOffset))
                {
                    style.BackColor = Color.DeepPink;
                }
            }


            switch (column)
            {
            case "label":
                style.ForeColor = Project.Data.GetLabelName(Project.Data.ConvertPCtoSnes(offset)) == "" ? Color.LightGray : style.ForeColor;
                break;

            case "base":
                style.ForeColor = Project.Data.GetBaseAddr(offset) > 0 /*&& Project.Data.GetFlag(offset) != Data.FlagType.Operand*/ ? Color.DarkBlue : Color.LightGray;
                break;

            case "ia":
                if (Project.Data.GetIndirectAddr(offset) > 0 /*&& Project.Data.GetFlag(offset) != Data.FlagType.Operand*/)
                {
                    style.ForeColor = Color.Red;
                }
                break;

            case "constant":
                if (constant != Data.ConstantType.Hexadecimal)
                {
                    style.BackColor = Color.FromArgb(50 - (int)constant, 100 - (int)constant, 255 - ((int)constant * 20));
                    style.ForeColor = Color.White;
                }
                break;

            case "comment":
                if (Project.Data.GetComment(Project.Data.ConvertPCtoSnes(offset)) == "")
                {
                    style.ForeColor = Color.LightGray;
                }
                break;
            }

            cell.PaintBackground(cell.CellBounds, true);
            if (sia >= 0)
            {
                if (column == "pc" && ((sia > selOffset && offset < sia && offset > selOffset) || (sia < selOffset && offset > sia && offset <= selOffset)))
                {
                    cell.Graphics.DrawLine(new Pen(Color.DeepPink, 2F), cell.CellBounds.Right - 2, cell.CellBounds.Top, cell.CellBounds.Right - 2, cell.CellBounds.Bottom);
                }
                if (((sia >= 0 && selOffset == offset - 1) || (ia >= 0 && ia == offset)) && column_index > ColumnIndex("pc") && column_index <= ColumnIndex("ia"))
                {
                    cell.Graphics.DrawLine(Pens.DeepPink, cell.CellBounds.Left, cell.CellBounds.Top, cell.CellBounds.Right, cell.CellBounds.Top);
                }
            }

            cell.Paint(cell.ClipBounds, DataGridViewPaintParts.ContentForeground);
            cell.Handled = true;
        }