Exemplo n.º 1
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 /// <param name="rom"></param>
 public Nes(byte[] rom)
 {
     this.Cartridge = NesCartridge.Load(rom);
     this.Controller = new NesGameController();
     this.Ppu = new Ppu.NesPpu(this.Cartridge.GetCopyChrRom1(), this.Cartridge.GetCopyChrRom2(), this.Cartridge.IsHMirror, this.Cartridge.IsVMirror, x => this.Image = x);
     this.MemoryMap = new Cpu.NesCpuMemoryMap(this.Cartridge.GetCopyPgRom1(), this.Cartridge.GetCopyPgRom2(), this.Ppu,this.Controller);
     this.Cpu = new Cpu.NesCpu(this.MemoryMap, this.Ppu);
 }
Exemplo n.º 2
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();
                        }
                    }
                }
            }