Example #1
0
            /// <summary>
            /// 指定ラインの画像情報を作成
            /// </summary>
            /// <param name="yLine"></param>
            internal void CreateLine(int yLine, NesPpu ppu)
            {
                if(yLine >= NesPpuScreenSize.MaxHeight)
                    return;

                int? disp1PointY = null;
                int? disp2PointY = null;

                if (yLine + ppu.Scroll.VScroll >= NesPpuScreenSize.MaxHeight)
                {
                    if (ppu.VMirror)
                        disp1PointY = disp2PointY = (yLine + ppu.Scroll.VScroll) - NesPpuScreenSize.MaxHeight;
                    else
                        disp2PointY = (yLine + ppu.Scroll.VScroll) - NesPpuScreenSize.MaxHeight;
                }
                else if (ppu.Scroll.VScroll > 0)
                {
                    if (ppu.VMirror)
                        disp1PointY = disp2PointY = yLine + ppu.Scroll.VScroll;
                    else
                        disp1PointY = yLine + ppu.Scroll.VScroll;
                }
                else
                {
                    if (ppu.VMirror)
                        disp1PointY = disp2PointY = yLine;
                    else
                        disp1PointY = yLine;
                }

                Func<NesPpu, int, NameTableType, byte[]> createBgFunc = (p, y, t) =>
                {
                    var namePoint = new NameTablePoint(0, y / Pattern.MaxHeight);
                    var nameIndex = NameTablePoint.ConvertIndex(namePoint);
                    var patternTable = p.PatternTables[p.ControlRegister1.BgPatternTableAdress];

                    return p.NameAttributePairTables[t].Item1
                        .Skip(nameIndex)
                        .Take(NameTable.MaxWidth)
                        .Select((x, i) =>
                        {
                            var pointTuple = NameTablePoint.ConvertPoint(i + nameIndex, NameTable.MaxWidth);
                            var point = new NameTablePoint(pointTuple.Item1, pointTuple.Item2);
                            var high2Bit = p.NameAttributePairTables[t].Item2.GetAttributeHigh2Bit(point);
                            return new { Data = x, HighBitData = high2Bit };
                        })
                        .Select(x => patternTable[x.Data].Select(xx => (byte)((x.HighBitData << 2) | xx)).ToArray())
                        .Buffer(32)
                        .SelectMany(x =>
                        {
                            var data = x;
                            byte[] buf = new byte[(Pattern.MaxWidth * Pattern.MaxHeight) * NameTable.MaxWidth];

                            for (int line = 0; line < 8; line++)
                            {
                                for (int i = 0; i < 32; i++)
                                {
                                    for (int j = 0; j < 8; j++)
                                    {
                                        var index = i * 8 + j + (line * 256);
                                        buf[index] = data[i][j + (line * 8)];
                                    }
                                }
                            }
                            return buf;
                        })
                        .ToArray();
                };
                Func<int, byte[], byte[]> getLineFunc = (y, t) =>
                {
                    var index = 0 + (y % Pattern.MaxHeight) * NesPpuScreenSize.MaxWidth;
                    return t.Skip(index).Take(NesPpuScreenSize.MaxWidth).ToArray();
                };

                // 画面1
                if (disp1PointY != null)
                {
                    if (!this.cacheDictionary.ContainsKey(Tuple.Create(NameTableType.Table0, disp1PointY.Value / Pattern.MaxHeight)))
                    {
                        var lineImage = createBgFunc(ppu, disp1PointY.Value, NameTableType.Table0);
                        this.cacheDictionary[Tuple.Create(NameTableType.Table0, disp1PointY.Value / Pattern.MaxHeight)] = lineImage;
                    }
                }
                // 画面2
                if (disp2PointY != null)
                {
                    if (!this.cacheDictionary.ContainsKey(Tuple.Create(NameTableType.Table1, disp2PointY.Value / Pattern.MaxHeight)))
                    {
                        var lineImage = createBgFunc(ppu, disp2PointY.Value, NameTableType.Table1);
                        this.cacheDictionary[Tuple.Create(NameTableType.Table1, disp2PointY.Value / Pattern.MaxHeight)] = lineImage;
                    }
                }

                // 横2画面
                if (disp1PointY != null && disp2PointY != null)
                {
                    var disp1Image = this.cacheDictionary[Tuple.Create(NameTableType.Table0, disp1PointY.Value / Pattern.MaxHeight)];
                    var disp2Image = this.cacheDictionary[Tuple.Create(NameTableType.Table1, disp2PointY.Value / Pattern.MaxHeight)];
                    if (ppu.Scroll.HScroll == 0)
                    {
                        this.lineDictionary[yLine] = getLineFunc(disp1PointY.Value, disp1Image);
                    }
                    else if (ppu.Scroll.HScroll >= NesPpuScreenSize.MaxWidth)
                    {
                        this.lineDictionary[yLine] = getLineFunc(disp2PointY.Value, disp2Image);
                    }
                    else
                    {
                        this.lineDictionary[yLine] = getLineFunc(disp1PointY.Value, disp1Image)
                            .Skip(ppu.Scroll.HScroll)
                            .Concat(
                                getLineFunc(disp2PointY.Value, disp2Image)
                                    .Take(ppu.Scroll.HScroll)
                            )
                            .ToArray();
                    }
                }
                // 縦2画面
                else
                {
                    if (disp1PointY != null)
                    {
                        var disp1Image = this.cacheDictionary[Tuple.Create(NameTableType.Table0, disp1PointY.Value / Pattern.MaxHeight)];
                        if (ppu.Scroll.HScroll == 0 || ppu.Scroll.HScroll >= NesPpuScreenSize.MaxWidth)
                        {
                            this.lineDictionary[yLine] = getLineFunc(disp1PointY.Value, disp1Image);
                        }
                        else
                        {
                            this.lineDictionary[yLine] = getLineFunc(disp1PointY.Value, disp1Image)
                            .Skip(ppu.Scroll.HScroll)
                            .Concat(
                                getLineFunc(disp1PointY.Value, disp1Image)
                                    .Take(ppu.Scroll.HScroll)
                            )
                            .ToArray();
                        }
                    }
                    else
                    {
                        var disp2Image = this.cacheDictionary[Tuple.Create(NameTableType.Table1, disp2PointY.Value / Pattern.MaxHeight)];
                        if (ppu.Scroll.HScroll == 0 || ppu.Scroll.HScroll >= NesPpuScreenSize.MaxWidth)
                        {
                            this.lineDictionary[yLine] = getLineFunc(disp2PointY.Value, disp2Image);
                        }
                        else
                        {
                            this.lineDictionary[yLine] = getLineFunc(disp2PointY.Value, disp2Image)
                            .Skip(ppu.Scroll.HScroll)
                            .Concat(
                                getLineFunc(disp2PointY.Value, disp2Image)
                                    .Take(ppu.Scroll.HScroll)
                            )
                            .ToArray();
                        }
                    }
                }
            }
Example #2
0
        /// <summary>
        /// BGイメージ情報をネーム・属性・パターンテーブルから作成
        /// </summary>
        /// <param name="p"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private IEnumerable<byte> ExpandBgImage(Tuple<NameTable, AttributeTable> p, PatternTable t)
        {
            //var bgImage = p.Item1
            //    .Select((x, i) =>
            //    {
            //        var point = PointAbstract.ConvertPoint<NameTablePoint>(i);
            //        var high2Bit = p.Item2.GetAttributeHigh2Bit(point);
            //        return new { Data = x, HighBitData = high2Bit };
            //    })
            //    .SelectMany(x => t[x.Data].Select(xx => (byte)((x.HighBitData << 2) | xx)))
            //    .Buffer(64)
            //    .Buffer(32)
            //    .SelectMany(x =>
            //    {
            //        var data = x.ToArray();
            //        byte[] buf = new byte[64 * 32];

            //        for (int line = 0; line < 8; line++)
            //        {
            //            for (int i = 0; i < 32; i++)
            //            {
            //                for (int j = 0; j < 8; j++)
            //                {
            //                    var index = i * 8 + j + (line * 256);
            //                    buf[index] = data[i][j + (line * 8)];
            //                }
            //            }
            //        }
            //        return buf;

            //        //return x.SelectMany(xx => xx.Select((xxx, i) => new { Data = xxx, PointY = i / 8 }))
            //        //    .GroupBy(xx => xx.PointY)
            //        //    .SelectMany(xx => xx.Select(xxx => xxx.Data));
            //    })
            //    .ToArray();

            var bgImage = p.Item1
                .Select((x, i) =>
                {
                    var pointTuple = NameTablePoint.ConvertPoint(i, NameTable.MaxWidth);
                    var point = new NameTablePoint(pointTuple.Item1, pointTuple.Item2);
                    var high2Bit = p.Item2.GetAttributeHigh2Bit(point);
                    return new { Data = x, HighBitData = high2Bit };
                })
                .Select(x => t[x.Data].Select(xx => (byte)((x.HighBitData << 2) | xx)).ToArray())
                .Buffer(32)
                .SelectMany(x =>
                {
                    var data = x;
                    byte[] buf = new byte[64 * 32];

                    for (int line = 0; line < 8; line++)
                    {
                        for (int i = 0; i < 32; i++)
                        {
                            for (int j = 0; j < 8; j++)
                            {
                                var index = i * 8 + j + (line * 256);
                                buf[index] = data[i][j + (line * 8)];
                            }
                        }
                    }
                    return buf;

                    // forループの処理に置き換えたのでコメントアウト
                    //return x.SelectMany(xx => xx.Select((xxx, i) => new { Data = xxx, PointY = i / 8 }))
                    //    .GroupBy(xx => xx.PointY)
                    //    .SelectMany(xx => xx.Select(xxx => xxx.Data));
                });

            return bgImage;
        }