Beispiel #1
0
        // Debug only
        public void RenderFullBgToImage(Bitmap bmp, bool renderViewPortBox, int bgSelect)
        {
            if (bgSelect == -1)
            {
                bgSelect = MemoryRegisters.LCDC.BgTileMapSelect;
            }

            TileMap tileMap = TileMaps[bgSelect];

            for (int y = 0; y < 256; y++)
            {
                for (int x = 0; x < 256; x++)
                {
                    Tile tile = tileMap.TileFromXY((byte)(x), (byte)(y));

                    bmp.SetPixel(x, y, Palettes.BackgroundPalette[tile.renderTile[x % 8, y % 8]]);
                }
            }

            if (renderViewPortBox)
            {
                byte viewPortX;
                byte viewPortY;

                // Where are we viewing the logical 256x256 tile map?
                viewPortX = MemoryRegisters.BgScrollX;
                viewPortY = MemoryRegisters.BgScrollY;

                Pen pen = new Pen(Color.RoyalBlue, 1.0f);
                using (var graphics = Graphics.FromImage(bmp))
                {
                    int x1 = viewPortX;
                    int x2 = viewPortX + Screen_X_Resolution;

                    int y1 = viewPortY;
                    int y2 = viewPortY + Screen_Y_Resolution;

                    // Each side can take 2 lines to draw if it wraps

                    int adjustX2 = x2;
                    if (x2 >= BG_Width_Pixels)
                    {
                        adjustX2 = x2 - BG_Width_Pixels;
                    }

                    int adjustY2 = y2;
                    if (y2 >= BG_Height_Pixels)
                    {
                        adjustY2 = y2 - BG_Height_Pixels;
                    }

                    // Top of rect (can go off end of image)
                    graphics.DrawLine(pen, x1, y1, x2, y1);
                    if (x2 != adjustX2)
                    {
                        graphics.DrawLine(pen, 0, y1, adjustX2, y1);
                    }

                    // Bottom of rect
                    graphics.DrawLine(pen, x1, adjustY2, x2, adjustY2);
                    if (x2 != adjustX2)
                    {
                        graphics.DrawLine(pen, 0, adjustY2, adjustX2, adjustY2);
                    }

                    // Left of rect (can go off end of image)
                    graphics.DrawLine(pen, x1, y1, x1, y2);
                    if (y2 != adjustY2)
                    {
                        graphics.DrawLine(pen, x1, 0, x1, adjustY2);
                    }

                    // Right
                    graphics.DrawLine(pen, adjustX2, y1, adjustX2, y2);
                    if (y2 != adjustY2)
                    {
                        graphics.DrawLine(pen, adjustX2, 0, adjustX2, adjustY2);
                    }
                }
            }
        }
Beispiel #2
0
        // Gamebopy screen resolution = 160x144
        void RenderScanline()
        {
            /*
             * // Very temporary
             * int offset = 0;
             * foreach (Tile t in Tiles)
             * {
             *  t.Parse(Memory.VRam, offset);
             *  offset += 16;
             * }
             */

            PpuAccessingVram = true;

            // Render the BG
            // Total BG size in VRam is 32x32 tiles
            // Viewport is 20x18 tiles
            if (MemoryRegisters.LCDC.BgWinDisplay == 1)
            {
                TileMap tileMap = TileMaps[MemoryRegisters.LCDC.BgTileMapSelect];

                byte screenY = CurrentScanline;

                // Where are we viewing the logical 256x256 tile map?
                byte viewPortX = MemoryRegisters.BgScrollX;
                byte viewPortY = MemoryRegisters.BgScrollY;

                int bgY = viewPortY + screenY;
                if (bgY >= 256)
                {
                    bgY -= 256;
                }

                // What row are we rendering within a tile?
                byte tilePixelY = (byte)(bgY % 8);

                for (byte screenX = 0; screenX < Screen_X_Resolution; screenX++)
                {
                    int bgX = viewPortX + screenX;
                    if (bgX >= 256)
                    {
                        bgX -= 256;
                    }

                    // What column are we rendering within a tile?
                    byte tilePixelX = (byte)(bgX % 8);

                    Tile tile = tileMap.TileFromXY((byte)(bgX), (byte)(bgY));

                    drawBuffer.SetPixel(screenX, screenY, Palettes.BackgroundPalette[tile.renderTile[tilePixelX, tilePixelY]]);
                }
            }


            // Render Window
            if (MemoryRegisters.LCDC.WindowDisplay == 1 &&
                MemoryRegisters.WindowX < Screen_X_Resolution &&
                MemoryRegisters.WindowY < Screen_Y_Resolution)
            {
                if (CurrentScanline >= MemoryRegisters.WindowY)
                {
                    TileMap tileMap = TileMaps[MemoryRegisters.LCDC.WindowTileMapSelect];

                    // Window X, Y tell you where on screen to start drawing the tiles found at 0,0 in the tilemap.
                    // The Window DOES NOT WRAP
                    // WindowX draws -7 pixels from its actual value
                    byte windowScreenSpaceX         = MemoryRegisters.WindowX;
                    byte windowScreenSpaceY         = MemoryRegisters.WindowY;
                    int  windowScreenSpaceXAdjusted = windowScreenSpaceX - 7;

                    // These track the X&Y in the tile map;
                    byte windowDataX = 0;
                    byte windowDataY = (byte)(CurrentScanline - windowScreenSpaceY);

                    int tilePixelY = (windowDataY % 8);

                    for (int x = windowScreenSpaceXAdjusted; x < Screen_X_Resolution; x++)
                    {
                        // Remember, this is window X adjusted by 7, so this is not wrapping
                        if (windowScreenSpaceXAdjusted < 0)
                        {
                            // Because of -7, the window can be offscreen for a few pixels
                            windowScreenSpaceXAdjusted++;
                            continue;
                        }
                        // What column are we rendering within a tile?
                        byte tilePixelX = (byte)(windowDataX % 8);

                        Tile tile = tileMap.TileFromXY(windowDataX, windowDataY);
                        drawBuffer.SetPixel(x, CurrentScanline, Palettes.BackgroundPalette[tile.renderTile[tilePixelX, tilePixelY]]);

                        windowScreenSpaceXAdjusted++;
                        windowDataX++;
                    }
                }
            }


            // Skip sprite rendering this line if a dma transfer has occured midframe and stomped all over the OAM entries.
            // OAM entries will become 'clean' after next OAM search (next line).
            if (OamDirty == false)
            {
                // Render Sprites, we already know that they all are visible on this scanline and they are already ordered so that the right most is first
                foreach (var sprite in oamSearchResults)
                {
                    byte sx = sprite.X;
                    byte sy = sprite.Y;

                    // can be negative
                    int spriteXScreenSpace = sx - 8;
                    int spriteYScreenSpace = sy - 16;

                    // Which row of the sprite is being rendered on this line?
                    int spriteYLine = CurrentScanline - spriteYScreenSpace;

                    Color[] palette = Palettes.ObjPalette0;
                    if (sprite.PaletteNumber == 1)
                    {
                        palette = Palettes.ObjPalette1;
                    }

                    Tile tile = null;
                    if (MemoryRegisters.LCDC.SpriteHeight == 0)
                    {
                        tile = GetSpriteTileByIndex(sprite.TileIndex);
                    }
                    // if using 16 pixel high sprites (2 tiles) then potentially adjust to the next tile and fix up the line if we are drawing the sewcond tile
                    // The tiles themselves also index opposite when Y flipped
                    else
                    {
                        if (spriteYLine >= 8)
                        {
                            if (sprite.YFlip == false)
                            {
                                tile = GetSpriteTileByIndex((byte)(sprite.TileIndex + 1));
                            }
                            else
                            {
                                tile = GetSpriteTileByIndex((byte)(sprite.TileIndex));
                            }
                            spriteYLine -= 8;
                        }
                        else
                        {
                            if (sprite.YFlip == false)
                            {
                                tile = GetSpriteTileByIndex((byte)(sprite.TileIndex));
                            }
                            else
                            {
                                tile = GetSpriteTileByIndex((byte)(sprite.TileIndex + 1));
                            }
                        }
                    }

                    for (int i = 0; i < 8; i++)
                    {
                        // Offscreen
                        if (spriteXScreenSpace + i >= Screen_X_Resolution)
                        {
                            break;
                        }

                        if (spriteXScreenSpace + i < 0)
                        {
                            continue;
                        }



                        int sprPixelX = i;
                        int sprPixelY = spriteYLine;
                        if (sprite.XFlip)
                        {
                            sprPixelX = 7 - sprPixelX;
                        }
                        if (sprite.YFlip)
                        {
                            sprPixelY = 7 - sprPixelY;
                        }
                        byte paletteIndex = tile.renderTile[sprPixelX, sprPixelY];

                        // If the priority is 0, sprites redner on top. If it is 1 then sprite pixels only render on top of 'white' otherwise they are obscured
                        if (sprite.ObjPriority == 1)
                        {
                            Color pixel = drawBuffer.GetPixel(spriteXScreenSpace + i, CurrentScanline);
                            if (pixel != Palettes.BackgroundPalette[0])
                            {
                                continue;
                            }
                        }

                        // Palette entry 0 == translucent for sprites
                        if (paletteIndex != 0)
                        {
                            drawBuffer.SetPixel(spriteXScreenSpace + i, CurrentScanline, palette[paletteIndex]);
                        }
                    }
                }
            }

            oamSearchResults.Clear();
            PpuAccessingVram = false;
        }