Esempio n. 1
0
File: PPU.cs Progetto: jizang/AprNes
        static void ppu_rendering_tick()
        {
            bool tile_decode_mode = ((0x10FFFF & (1u << (ppu_cycles_x / 16))) != 0) ? true : false;  // When x is 0..255, 320..335

            if (tile_decode_mode)
            {
                switch (ppu_cycles_x & 7)
                {
                case 0: ioaddr = 0x2000 + (vram_addr & 0xFFF); break;                                                    //get NT address

                case 1: NTVal = ppu_ram[ioaddr]; break;                                                                  //get NT content

                case 2: ioaddr = 0x23C0 | (vram_addr & 0xC00) | (vram_addr >> 4 & 0x38) | (vram_addr >> 2 & 0x7); break; //get AT address

                case 3: ATVal = (byte)(ppu_ram[ioaddr] >> (((vram_addr >> 4 & 0x04) | (vram_addr & 0x02)))); break;      //get AT content

                case 4: ioaddr = BgPatternTableAddr | (NTVal << 4) | (vram_addr >> 12 & 7); break;                       //get low tile address

                case 5: lowTile = MapperObj.MapperR_CHR(ioaddr); break;                                                  //get low tile content

                case 6: ioaddr = BgPatternTableAddr | (NTVal << 4) | (vram_addr >> 12 & 7) | 8; break;                   //get high tile address

                case 7: highTile = MapperObj.MapperR_CHR(ioaddr); break;                                                 //get high tile content
                }
            }
            else if (ppu_cycles_x < 320)
            {
            }
            //ignore unused NT fetches
        }
Esempio n. 2
0
File: PPU.cs Progetto: jizang/AprNes
 static int GetAttr()
 {
     vram_addr_limite = vram_addr & 0x3FF;
     attrAddr         = (ushort)(0x23C0 | (vram_addr & 0xC00) | (((vram_addr_limite >> 2) & 0x07) | (((vram_addr_limite >> 4) & 0x38) | 0x3C0)));
     tileAddr         = (ushort)((vram_addr & 0xc00) | 0x2000 | vram_addr_limite);
     array_loc        = (ppu_ram[tileAddr] << 4) + BgPatternTableAddr + ((scanline + scrol_y) & 7);
     lowshift         = (ushort)((lowshift << 8) | MapperObj.MapperR_CHR(array_loc));
     highshift        = (ushort)((highshift << 8) | MapperObj.MapperR_CHR(array_loc + 8));
     if ((vram_addr & 0x1F) == 0x1F)
     {
         vram_addr ^= 0x41F;
     }
     else
     {
         vram_addr++;
     }
     return((ppu_ram[attrAddr] >> (((vram_addr_limite >> 4) & 0x04) | (vram_addr_limite & 0x02))) & 0x03);
 }
Esempio n. 3
0
File: PPU.cs Progetto: jizang/AprNes
        static void RenderSpritesLine()
        {
            int  spriteCount = 0, line_t = 0, loc_t, oam_addr = 0, line, tile_th_t, y_loc = 0, offset, mask;
            byte tile_th, tile_hbyte, tile_lbyte;
            bool flip_x = false;

            for (int oam_th = 63; oam_th >= 0; oam_th--)
            {
                oam_addr = oam_th << 2;
                y_loc    = spr_ram[oam_addr];

                if ((!(y_loc > scanline || scanline - y_loc > (Spritesize8x16 ? 15 : 7))) && ((++spriteCount) == 9))//this line ref halfnes way
                {
                    isSpriteOverflow = true;
                }

                if (!ShowSprites)
                {
                    continue;
                }

                y_loc++;
                if (Spritesize8x16)
                {
                    if (scanline < y_loc || scanline > (y_loc + 15))
                    {
                        continue;                                             //15
                    }
                    byte byte0 = spr_ram[oam_addr | 1];
                    tile_th = (byte)((byte0 & 0xfe) >> 0);
                    if ((byte0 & 1) > 0)
                    {
                        offset = 256;
                    }
                    else
                    {
                        offset = 0;
                    }
                }
                else
                {
                    if (scanline < y_loc || scanline > (y_loc + 7))
                    {
                        continue;                                            //7
                    }
                    tile_th = spr_ram[oam_addr | 1];
                    offset  = SpPatternTableAddr >> 4;
                }


                byte sprite_attr = spr_ram[oam_addr | 2];
                byte x_loc       = spr_ram[oam_addr | 3];
                bool priority    = ((sprite_attr & 0x20) > 0) ? true : false;
                if (scanline >= y_loc && scanline <= (y_loc + 7))
                {
                    tile_th_t = tile_th + offset;
                    line      = scanline - y_loc;
                }
                else
                {
                    tile_th_t = tile_th + offset + 1;
                    line      = (scanline - y_loc) - 8;
                }

                if ((sprite_attr & 0x80) > 0)
                {
                    line_t = (7 - line);
                }
                else
                {
                    line_t = line;
                }

                tile_hbyte = MapperObj.MapperR_CHR((tile_th_t << 4) | (line_t + 8));
                tile_lbyte = MapperObj.MapperR_CHR((tile_th_t << 4) | line_t);
                flip_x     = ((sprite_attr & 0x40) > 0) ? true : false;

                for (int loc = 0; loc < 8; loc++)
                {
                    if ((x_loc + loc) > 255)
                    {
                        continue;
                    }
                    if (flip_x)
                    {
                        loc_t = (7 - loc);
                    }
                    else
                    {
                        loc_t = loc;
                    }
                    mask      = 1 << (7 - loc_t);
                    pixel     = (((tile_hbyte & mask) << 1) + (tile_lbyte & mask)) >> ((7 - loc_t));
                    array_loc = ((scanline) << 8) + (x_loc + loc);
                    if (oam_th == 0 && !isSprite0hit && pixel != 0 && Buffer_BG_array[array_loc] != 0 && (x_loc + loc) != 255 && ShowBackGround)
                    {
                        isSprite0hit = true; //fixed 2017.0119 add  (x_loc + loc) != 255
                    }
                    if (pixel != 0 && (Buffer_BG_array[array_loc] == 0 || (Buffer_BG_array[array_loc] != 0 && !priority)))
                    {
                        ScreenBuf1x[array_loc] = NesColors[ppu_ram[0x3f10 + ((sprite_attr & 3) << 2) | pixel] & 0x3f];
                    }
                }
            }
        }
Esempio n. 4
0
        static void init_function()
        {
            mem_write_fun = new Action <ushort, byte> [0x10000];
            mem_read_fun  = new Func <ushort, byte> [0x10000];

            ppu_write_fun = new Action <byte> [0x10000];
            ppu_read_fun  = new Func <int, byte> [0x10000];

            for (int address = 0; address < 0x10000; address++)
            {
                if (address < 0x2000)
                {
                    mem_write_fun[address] = new Action <ushort, byte>((addr, val) => { NES_MEM[addr & 0x7ff] = val; });
                }
                else if (address < 0x4020)
                {
                    mem_write_fun[address] = new Action <ushort, byte>(IO_write);
                }
                else if (address < 0x6000)
                {
                    mem_write_fun[address] = new Action <ushort, byte>(MapperObj.MapperW_ExpansionROM);
                }
                else if (address < 0x8000)
                {
                    mem_write_fun[address] = new Action <ushort, byte>(MapperObj.MapperW_RAM);
                }
                else
                {
                    mem_write_fun[address] = new Action <ushort, byte>(MapperObj.MapperW_PRG);
                }
            }
            for (int address = 0; address < 0x10000; address++)
            {
                if (address < 0x2000)
                {
                    mem_read_fun[address] = new Func <ushort, byte>((addr) => { return(NES_MEM[addr & 0x7ff]); });
                }
                else if (address < 0x4020)
                {
                    mem_read_fun[address] = new Func <ushort, byte>(IO_read);
                }
                else if (address < 0x6000)
                {
                    mem_read_fun[address] = new Func <ushort, byte>(MapperObj.MapperR_ExpansionROM);
                }
                else if (address < 0x8000)
                {
                    mem_read_fun[address] = new Func <ushort, byte>(MapperObj.MapperR_RAM);
                }
                else
                {
                    mem_read_fun[address] = new Func <ushort, byte>(MapperObj.MapperR_RPG);
                }
            }


            for (int address = 0; address < 0x10000; address++)
            {
                int vram_addr_wrap = 0;
                if ((address & 0x3F00) == 0x3F00)
                {
                    vram_addr_wrap = address & 0x2FFF;

                    if (vram_addr_wrap < 0x2000)
                    {
                        ppu_read_fun[address] = new Func <int, byte>((val) =>
                        {
                            ppu_2007_temp   = ppu_ram[val & ((val & 0x03) == 0 ? 0x0C : 0x1F) + 0x3f00];
                            ppu_2007_buffer = MapperObj.MapperR_CHR(val & 0x2FFF);

                            ppu_2007_temp = (byte)((openbus & 0xC0) | (ppu_2007_temp & 0x3F));//add openbus fix


                            vram_addr            = (ushort)((val + VramaddrIncrement) & 0x7FFF);
                            openbus              = ppu_2007_temp;
                            open_bus_decay_timer = 77777;//fixed add

                            return(openbus);
                        });
                    }
                    else
                    {
                        ppu_read_fun[address] = new Func <int, byte>((val) =>
                        {
                            ppu_2007_temp   = ppu_ram[val & ((val & 0x03) == 0 ? 0x0C : 0x1F) + 0x3f00];
                            ppu_2007_buffer = ppu_ram[val & 0x2FFF];

                            ppu_2007_temp = (byte)((openbus & 0xC0) | (ppu_2007_temp & 0x3F));//add openbus fix

                            vram_addr            = (ushort)((val + VramaddrIncrement) & 0x7FFF);
                            openbus              = ppu_2007_temp;
                            open_bus_decay_timer = 77777;//fixed add
                            return(openbus);
                        });
                    }
                }
                else
                {
                    vram_addr_wrap = address & 0x3FFF;

                    if (vram_addr_wrap < 0x2000)
                    {
                        ppu_read_fun[address] = new Func <int, byte>((val) =>
                        {
                            ppu_2007_temp        = ppu_2007_buffer;                     //need read from buffer
                            ppu_2007_buffer      = MapperObj.MapperR_CHR(val & 0x3FFF); //Pattern Table
                            vram_addr            = (ushort)((val + VramaddrIncrement) & 0x7FFF);
                            openbus              = ppu_2007_temp;
                            open_bus_decay_timer = 77777;//fixed add
                            return(openbus);
                        });
                    }
                    else if (vram_addr_wrap < 0x3F00)
                    {
                        ppu_read_fun[address] = new Func <int, byte>((val) =>
                        {
                            ppu_2007_temp        = ppu_2007_buffer;       //need read from buffer
                            ppu_2007_buffer      = ppu_ram[val & 0x3FFF]; //Name Table & Attribute Table
                            vram_addr            = (ushort)((val + VramaddrIncrement) & 0x7FFF);
                            openbus              = ppu_2007_temp;
                            open_bus_decay_timer = 77777;//fixed add
                            return(openbus);
                        });
                    }
                    else
                    {
                        ppu_read_fun[address] = new Func <int, byte>((val) =>
                        {
                            ppu_2007_temp        = ppu_2007_buffer;                                                                   //need read from buffer
                            int _vram_addr_wrap  = val & 0x2FFF;
                            ppu_2007_buffer      = ppu_ram[_vram_addr_wrap & ((_vram_addr_wrap & 0x03) == 0 ? 0x0C : 0x1F) + 0x3f00]; // //Sprite Palette & Image Palette
                            vram_addr            = (ushort)((val + VramaddrIncrement) & 0x7FFF);
                            openbus              = ppu_2007_temp;
                            open_bus_decay_timer = 77777;//fixed add
                            return(openbus);
                        });
                    }
                }
            }


            for (int address = 0; address < 0x10000; address++)
            {
                int vram_addr_wrap = 0;

                vram_addr_wrap = address & 0x3FFF;
                if (vram_addr_wrap < 0x2000)
                {
                    ppu_write_fun[address] = new Action <byte>((val) =>
                    {
                        int _vram_addr_wrap = vram_addr & 0x3FFF;
                        openbus             = val;
                        if (CHR_ROM_count == 0)
                        {
                            ppu_ram[_vram_addr_wrap] = val;
                        }
                        vram_addr = (ushort)((vram_addr + VramaddrIncrement) & 0x7FFF);
                    });
                }
                else if (vram_addr_wrap < 0x3f00) //Name Table & Attribute Table
                {
                    ppu_write_fun[address] = new Action <byte>((val) =>
                    {
                        int _vram_addr_wrap = vram_addr & 0x3FFF;
                        int _addr_range     = _vram_addr_wrap & 0xc00;
                        openbus             = val;
                        if (*Vertical != 0)
                        {
                            if (_addr_range < 0x800)
                            {
                                ppu_ram[_vram_addr_wrap] = ppu_ram[_vram_addr_wrap | 0x800] = val;
                            }
                            else
                            {
                                ppu_ram[_vram_addr_wrap] = ppu_ram[_vram_addr_wrap & 0x37ff] = val;
                            }
                        }
                        else
                        {
                            if (_addr_range < 0x400)
                            {
                                ppu_ram[_vram_addr_wrap] = ppu_ram[_vram_addr_wrap | 0x400] = val;
                            }
                            else if (_addr_range < 0x800)
                            {
                                ppu_ram[_vram_addr_wrap] = ppu_ram[_vram_addr_wrap & 0x3bff] = val;
                            }
                            else if (_addr_range < 0xc00)
                            {
                                ppu_ram[_vram_addr_wrap] = ppu_ram[_vram_addr_wrap | 0x400] = val;
                            }
                            else
                            {
                                ppu_ram[_vram_addr_wrap] = ppu_ram[_vram_addr_wrap & 0x3bff] = val;
                            }
                        }
                        vram_addr = (ushort)((vram_addr + VramaddrIncrement) & 0x7FFF);
                    });
                }
                else
                {
                    ppu_write_fun[address] = new Action <byte>((val) =>
                    {
                        int _vram_addr_wrap = vram_addr & 0x3FFF;
                        openbus             = val;
                        ppu_ram[(_vram_addr_wrap & ((_vram_addr_wrap & 0x03) == 0 ? 0x0C : 0x1F)) + 0x3f00] = val; //Sprite Palette & Image Palette
                        vram_addr = (ushort)((vram_addr + VramaddrIncrement) & 0x7FFF);
                    });
                }
            }
        }