示例#1
0
        public void DumpBgTiles()
        {
            var image = new DirectBitmap(256, 256);

            int vramBaseOffset0 = 0x0;
            int vramBaseOffset1 = 0x8000;

            Color[] palette = LcdController.Palettes.Palette0;

            // You have to supply the code to get the tiles palette
            Func <int, int> get4BitPaletteNumber = (int tileNumber) => {
                for (int i = 0; i < 4; i++)
                {
                    int pal = TileHelpers.FindBgPaletteForTile(tileNumber, LcdController.Bg[i].TileMap);
                    if (pal != 0)
                    {
                        return(pal * 16);
                    }
                }
                return(0);
            };

            DebugDrawTiles(image, Memory.VRam, vramBaseOffset0, palette, false, get4BitPaletteNumber);
            image.Bitmap.Save(string.Format("../../../../dump/{0}Tiles{1}_{2}.png", "BGV0", "4bpp", Rom.RomName));

            DebugDrawTiles(image, Memory.VRam, vramBaseOffset1, palette, false, get4BitPaletteNumber);
            image.Bitmap.Save(string.Format("../../../../dump/{0}Tiles{1}_{2}.png", "BGV1", "4bpp", Rom.RomName));

            DebugDrawTiles(image, Memory.VRam, vramBaseOffset0, palette, true, get4BitPaletteNumber);
            image.Bitmap.Save(string.Format("../../../../dump/{0}Tiles{1}_{2}.png", "BGV0", "8bpp", Rom.RomName));

            DebugDrawTiles(image, Memory.VRam, vramBaseOffset1, palette, true, get4BitPaletteNumber);
            image.Bitmap.Save(string.Format("../../../../dump/{0}Tiles{1}_{2}.png", "BGV1", "8bpp", Rom.RomName));
        }
示例#2
0
        public int PixelValue(int screenX, int screenY)
        {
            int paletteOffset = 0;

            int scrollX = ScrollX;

            if (scrollX >= bgWidthInPixel)
            {
                scrollX -= bgWidthInPixel;
            }

            int scrollY = ScrollY;

            if (scrollY >= bgHeightInPixel)
            {
                scrollY -= bgHeightInPixel;
            }

            int wrappedBgY = scrollY + screenY;

            if (wrappedBgY >= bgHeightInPixel)
            {
                wrappedBgY -= bgHeightInPixel;
            }

            // Which line within the current tile are we rendering?
            int tileRow = wrappedBgY % 8;

            // If we reach the edge of the Bg, wrap around
            int wrappedBgX = scrollX + screenX;

            if (wrappedBgX >= bgWidthInPixel)
            {
                wrappedBgX -= bgWidthInPixel;
            }

            // Which column within the current tile are we rendering?
            int tileColumn = wrappedBgX % 8;

            var tileMetaData = TileMap.TileMapItemFromBgXY(wrappedBgX, wrappedBgY);

            // If we are in 4 bpp mode the tilemap contains which 16 colour palette to use. 16 entries per palette
            if (eightBitColour == false)
            {
                paletteOffset = tileMetaData.Palette * 16;
            }

            int tileVramOffset = (int)(tileDataVramOffset + ((tileMetaData.TileNumber) * tileSize));

            int paletteIndex = TileHelpers.GetTilePixel(tileColumn, tileRow, eightBitColour, gba.Memory.VRam, tileVramOffset, tileMetaData.FlipHorizontal, tileMetaData.FlipVertical);

            if (paletteIndex == 0)
            {
                return(0);
            }

            return(paletteOffset + paletteIndex);
        }
示例#3
0
文件: Obj.cs 项目: 5l1v3r1/Y2Gba
        // What is the pixel value within the sprite. passing 0,0 returns the pixel value of the top left of this sprite
        public int PixelValue(int spriteX, int spriteY)
        {
            Size spriteDimensions = Attributes.Dimensions;

            if (spriteX < 0 || spriteX >= spriteDimensions.Width ||
                spriteY < 0 || spriteY >= spriteDimensions.Height)
            {
                return(0);
            }

            int currentSpriteColumnInTiles = spriteX / 8;
            int currentSpriteRowInTiles    = spriteY / 8;

            int currentColumnWithinTile = spriteX % 8;
            int currentRowWithinTile    = spriteY % 8;

            if (hFlip)
            {
                currentSpriteColumnInTiles = (spriteWidthInTiles - 1) - currentSpriteColumnInTiles;
            }
            if (vFlip)
            {
                currentSpriteRowInTiles = (spriteHeightInTiles - 1) - currentSpriteRowInTiles;
            }

            // This offset will be set to point to the start of the 8x8 that spriteX,spriteY is within
            int vramTileOffset;

            // We count tile sizes in 4bpp when measuring tile rows / tile grid position

            // Addressing mode (1d / 2d)
            if (TileMapping2D)
            {
                // 2D addressing, vram is thought of as a 32x32 matrix of tiles. A sprites tiles are arranged as you would view them on a screen
                int full32TileRowSizeInBytes = LcdController.Tile_Size_4bit * 32;
                vramTileOffset = vramBaseOffset + offsetToFirstTile + (currentSpriteRowInTiles * full32TileRowSizeInBytes) + (currentSpriteColumnInTiles * tileSize);
            }
            else
            {
                // 1D addressing, all the sprites tiles are contiguous in vram
                vramTileOffset = vramBaseOffset + offsetToFirstTile + (currentSpriteRowInTiles * spriteRowSizeInBytes) + (currentSpriteColumnInTiles * tileSize);
            }

            // Lookup the actual pixel value (which is a palette index) in the tile data
            int paletteIndex = TileHelpers.GetTilePixel(currentColumnWithinTile, currentRowWithinTile, eightBitColour, gba.Memory.VRam, vramTileOffset, hFlip, vFlip);

            // Pal 0 == Transparent
            if (paletteIndex == 0)
            {
                return(0);
            }

            return(paletteOffset + paletteIndex);
        }
示例#4
0
        // Code to dump both BG and Obj tiles. Quite a complex list of parameters in order to make it work for both
        public void DebugDrawTiles(DirectBitmap image, byte[] vram, int vramBaseOffset, Color[] palette, bool eightBitColour, Func <int, int> getTile4BitPaletteNumber)
        {
            int tileCountX = 32;
            int tileCountY = 32;

            int tileX = 0;
            int tileY = 0;

            int tileSize = eightBitColour ? LcdController.Tile_Size_8bit: LcdController.Tile_Size_4bit;

            int totalTiles = eightBitColour ? 512 : 1024;

            for (int tileNumber = 0; tileNumber < totalTiles; tileNumber++)
            {
                int tileVramOffset = vramBaseOffset + (tileNumber * tileSize);

                int paletteOffset = 0;
                if (eightBitColour == false && getTile4BitPaletteNumber != null)
                {
                    paletteOffset = getTile4BitPaletteNumber(tileNumber);
                }

                // Add one tiles pixels
                for (int y = 0; y < 8; y++)
                {
                    for (int x = 0; x < 8; x++)
                    {
                        int paletteIndex = TileHelpers.GetTilePixel(x, y, eightBitColour, vram, tileVramOffset, false, false);

                        // 0 == transparent / pal 0
                        int colIndex = (paletteIndex == 0 ? 0 : paletteOffset + paletteIndex);

                        image.SetPixel(x + (tileX * 8), y + (tileY * 8), palette[colIndex]);
                    }
                }

                // Coordinates on the output image
                tileX++;
                if (tileX == tileCountX)
                {
                    tileX = 0;
                    tileY++;
                }
            }

            bool drawGrid = true;

            if (drawGrid)
            {
                GfxHelpers.DrawGrid(image.Bitmap, Color.FromArgb(64, 0, 0, 0), 0, 0, tileCountX, tileCountY, 8, 8);
            }
        }
示例#5
0
文件: Background.cs 项目: Y2JB/Y2Gba
        // Used for debug rendering BG's. Renders the source BG, does not scroll etc
        public void DebugRenderScanline(int scanline, int scanlineWidth, DirectBitmap drawBuffer)
        {
            Color[] palette       = gba.LcdController.Palettes.Palette0;
            int     paletteOffset = 0;

            bool eightBitColour = (CntRegister.PaletteMode == BgPaletteMode.PaletteMode256x1);

            // Which line within the current tile are we rendering?
            int tileRow = scanline % 8;

            for (int x = 0; x < scanlineWidth; x++)
            {
                // Which column within the current tile are we rendering?
                int tileColumn = x % 8;

                var tileMetaData = TileMap.TileMapItemFromBgXY(x, scanline);

                // If we are in 4 bpp mode the tilemap contains which 16 colour palette to use. 16 entries per palette
                if (eightBitColour == false)
                {
                    paletteOffset = tileMetaData.Palette * 16;
                }

                int tileSize = (eightBitColour ? LcdController.Tile_Size_8bit : LcdController.Tile_Size_4bit);

                // 4 bytes represent one row of pixel data for a single tile
                int tileVramOffset = (int)(tileDataVramOffset + ((tileMetaData.TileNumber) * tileSize));

                // Sometimes Bg's can be set up with invalid data which won't be drawn
                if (tileVramOffset >= gba.Memory.VRam.Length)
                {
                    continue;
                }

                int paletteIndex = TileHelpers.GetTilePixel(tileColumn, tileRow, eightBitColour, gba.Memory.VRam, tileVramOffset, tileMetaData.FlipHorizontal, tileMetaData.FlipVertical);

                // Pal 0 == Transparent
                if (paletteIndex == 0)
                {
                    continue;
                }

                drawBuffer.SetPixel(x, scanline, palette[paletteOffset + paletteIndex]);
            }
        }
示例#6
0
文件: Background.cs 项目: Y2JB/Y2Gba
        // Used for debug rendering BG's. Renders the source BG, does not scroll etc
        public void DebugRenderScanlineAffine(int scanline, int scanlineWidth, DirectBitmap drawBuffer)
        {
            Color[] palette        = gba.LcdController.Palettes.Palette0;
            bool    eightBitColour = CntRegister.PaletteMode == BgPaletteMode.PaletteMode256x1;

            // Which line within the current tile are we rendering?
            int tileRow = scanline % 8;

            for (int x = 0; x < scanlineWidth; x++)
            {
                // Coords (measured in tiles) of the tile we want to render
                int bgRow    = scanline / 8;
                int bgColumn = x / 8;

                // Which row / column within the tile we are rendering?
                int tileColumn = x % 8;

                // Affine BG's have one byte screen data (the tile index). Also all tiles are 8bpp
                // Affine BG's are also all square (they have their own size table which is different to regular tiled bg's)
                int tileInfoOffset = (bgRow * bgWidthInTiles) + bgColumn;

                int tileNumber = gba.Memory.VRam[(CntRegister.ScreenBlockBaseAddress * 2048) + tileInfoOffset];

                int tileVramOffset = (int)(tileDataVramOffset + (tileNumber * tileSize));

                // Sometimes Bg's can be set up with invalid data which won't be drawn
                if (tileVramOffset >= gba.Memory.VRam.Length)
                {
                    continue;
                }

                int paletteIndex = TileHelpers.GetTilePixel(tileColumn, tileRow, true, gba.Memory.VRam, tileVramOffset, false, false);

                // Pal 0 == Transparent
                if (paletteIndex == 0)
                {
                    continue;
                }

                drawBuffer.SetPixel(x, scanline, palette[paletteIndex]);
            }
        }
示例#7
0
        public void DumpObjTiles()
        {
            var image = new DirectBitmap(256, 256);

            // OBJ Tiles are stored in a separate area in VRAM: 06010000-06017FFF (32 KBytes) in BG Mode 0-2, or 06014000-06017FFF (16 KBytes) in BG Mode 3-5.
            // We dump the whole memory area in both 4 and 8 bit modes. Some will look wrong depending on Bg mode, colour depth etc
            int vramBaseOffset = 0x00010000;

            Color[] palette = LcdController.Palettes.Palette1;

            // You have to supply the code to get the tiles palette
            Func <int, int> get4BitPaletteNumber = (int tileNumber) => {
                Obj obj = TileHelpers.FindFirstSpriteThatUsesTile(tileNumber, LcdController.ObjController.Obj);
                return(obj == null ? 0 : obj.Attributes.PaletteNumber * 16);
            };

            DebugDrawTiles(image, Memory.VRam, vramBaseOffset, palette, true, get4BitPaletteNumber);
            image.Bitmap.Save(string.Format("../../../../dump/{0}Tiles{1}_{2}.png", "Obj", "8bpp", Rom.RomName));

            DebugDrawTiles(image, Memory.VRam, vramBaseOffset, palette, false, get4BitPaletteNumber);
            image.Bitmap.Save(string.Format("../../../../dump/{0}Tiles{1}_{2}.png", "Obj", "4bpp", Rom.RomName));
        }
示例#8
0
文件: Background.cs 项目: Y2JB/Y2Gba
        public int PixelValueAffine(int screenX, int screenY)
        {
            // Scrolling values set the origin so that BG 0,0 == Screen 0,0
            // Affine scroll are 24.8 fixed point numbers but as long as you shift away the fraction part at the end, you can just do integer math on them and they work
            int scrollX = AffineScrollXCached; // >> 8;
            int scrollY = AffineScrollYCached; // >> 8;

            // The game will have set up the matrix to be the inverse texture mapping matrix. I.E it maps from screen space to texture space. Just what we need!
            int textureSpaceX, textureSpaceY;

            textureSpaceX = ((scrollX + (AffineMatrix.Pa * screenX)) >> 8);
            textureSpaceY = ((scrollY + (AffineMatrix.Pc * screenX)) >> 8);

            //AffineMatrix.Multiply(screenX, screenY, out textureSpaceX, out textureSpaceY);

            // Apply displacement vector (affine scroll)
            // textureSpaceX += scrollX;
            // textureSpaceY += scrollY;

            // BG Wrap?
            if (CntRegister.DisplayAreaOverflow)
            {
                /*
                 * while (textureSpaceX >= bgWidthInPixel) textureSpaceX -= bgWidthInPixel;
                 * while (textureSpaceY >= bgHeightInPixel) textureSpaceY -= bgHeightInPixel;
                 * while (textureSpaceX < 0) textureSpaceX += bgWidthInPixel;
                 * while (textureSpaceY < 0) textureSpaceY += bgHeightInPixel;
                 */
                textureSpaceX &= (bgWidthInPixel - 1);
                textureSpaceY &= (bgHeightInPixel - 1);
            }
            else
            {
                if (textureSpaceX < 0 || textureSpaceX >= bgWidthInPixel)
                {
                    return(0);
                }
                if (textureSpaceY < 0 || textureSpaceY >= bgHeightInPixel)
                {
                    return(0);
                }
            }


            // Coords (measured in tiles) of the tile we want to render
            //int bgRow = textureSpaceY / 8;
            //int bgColumn = textureSpaceX / 8;

            // Which row / column within the tile we are rendering?
            int tileRow    = textureSpaceY % 8;
            int tileColumn = textureSpaceX % 8;

            // Affine BG's have one byte screen data (the tile index). Also all tiles are 8bpp
            // Affine BG's are also all square (they have their own size table which is different to regular tiled bg's)
            //int tileInfoOffset = (bgRow * bgWidthInTiles) + bgColumn;
            uint tileInfoOffset = ((CntRegister.ScreenBlockBaseAddress * 2048u) | (uint)((textureSpaceY >> 3) * ((uint)bgWidthInPixel >> 3)) | (uint)(textureSpaceX >> 3));
            int  tileNumber     = gba.Memory.VRam[tileInfoOffset];

            int tileVramOffset = (int)(tileDataVramOffset + (tileNumber * tileSize));

            // Sometimes Bg's can be set up with invalid data which won't be drawn
            if (tileVramOffset >= gba.Memory.VRam.Length)
            {
                return(0);
            }

            int paletteIndex = TileHelpers.GetTilePixel(tileColumn, tileRow, true, gba.Memory.VRam, tileVramOffset, false, false);

            return(paletteIndex);
        }
示例#9
0
        private void RenderScanlineTextMode()
        {
            ObjPrioritySort();

            int scanline = CurrentScanline;
            bool windowing = (DisplayControlRegister.DisplayWin0 || DisplayControlRegister.DisplayWin1 || DisplayControlRegister.DisplayWin1 || DisplayControlRegister.DisplayObjWin);

            // We render front to back. Once a pixel is drawn we stop going through the layers.
            // TODO: In order to do blending we may need to go through all the layers for each pixel
#if ParallelizeScanline
            var paritioner = Partitioner.Create(0, LcdController.Screen_X_Resolution, 80);
            var result = Parallel.ForEach(paritioner, (range) =>
            {
            for (int x = range.Item1; x < range.Item2; x++)
#else
            for (int x = 0; x < Screen_X_Resolution; x++)
#endif
            {
                int paletteIndex;
                bool pixelDrawn = false;

                // Windowing can disable obj's and bg's
                bool objVisibleOverride = false;

                int windowRegion = 0;

                int bgVisibleOverride = 0; // bitmask for bg visible (from window)
                if (windowing)
                {
                    windowRegion = TileHelpers.PixelWindowRegion(x, CurrentScanline, gba);

                    // 0 is outside of all windows
                    if (windowRegion == 0)
                    {
                        objVisibleOverride = Windows[(int) Window.WindowName.WindowOut].DisplayObjs;

                        bgVisibleOverride = Windows[(int)Window.WindowName.WindowOut].DisplayBg0 |
                                            Windows[(int)Window.WindowName.WindowOut].DisplayBg1 |
                                            Windows[(int)Window.WindowName.WindowOut].DisplayBg2 |
                                            Windows[(int)Window.WindowName.WindowOut].DisplayBg3;
                    }
                    // Window 0 takes priority over window 1. We don't need to check if the point is within both areas as it is done in the function call above
                    else if((windowRegion & (int)TileHelpers.WindowRegion.Window0) != 0)
                    {
                        objVisibleOverride = Windows[(int)Window.WindowName.Window0].DisplayObjs;

                        bgVisibleOverride = Windows[(int)Window.WindowName.Window0].DisplayBg0 |
                                            Windows[(int)Window.WindowName.Window0].DisplayBg1 |
                                            Windows[(int)Window.WindowName.Window0].DisplayBg2 |
                                            Windows[(int)Window.WindowName.Window0].DisplayBg3;

                    }
                    else if ((windowRegion & (int)TileHelpers.WindowRegion.Window1) != 0)
                    {
                        objVisibleOverride = Windows[(int)Window.WindowName.Window1].DisplayObjs;

                        bgVisibleOverride = Windows[(int)Window.WindowName.Window1].DisplayBg0 |
                                            Windows[(int)Window.WindowName.Window1].DisplayBg1 |
                                            Windows[(int)Window.WindowName.Window1].DisplayBg2 |
                                            Windows[(int)Window.WindowName.Window1].DisplayBg3;
                    }


                }
                else
                {
                    objVisibleOverride = true;
                    bgVisibleOverride = 0;
                }

                // Start at the top priority, if something draws to the pixel, we can early out and stop processing this pixel 
                for (int priority = 0; priority < 4; priority++)
                {
                    // Sprite rendering
                    if (DisplayControlRegister.DisplayObj &&
                        (!windowing || (windowing && objVisibleOverride)))
                    {
                        pixelDrawn = RenderSpritePixel(x, scanline, priority, windowing, windowRegion, ref bgVisibleOverride);
                        if (pixelDrawn)
                        {
                            break;
                        }                        
                    }

                    // No Sprite occupied this pixel, move on to backgrounds

                    // Bg Rendering
                    // Find the background with this priority                        
                    for (int bgSelect = 0; bgSelect < 4; bgSelect++)
                    {
                        if (Bg[bgSelect].CntRegister.Priority != priority ||
                            DisplayControlRegister.BgVisible(Bg[bgSelect].BgNumber) == false ||
                            (windowing && ((bgVisibleOverride & (1 << bgSelect)) == 0)))
                        {
                            continue;
                        }

                        if (Bg[bgSelect].AffineMode)
                        {
                            paletteIndex = Bg[bgSelect].PixelValueAffine(x, scanline);
                        }
                        else
                        {
                            paletteIndex = Bg[bgSelect].PixelValue(x, scanline);
                        }

                        // Pal 0 == Transparent 
                        if (paletteIndex == 0)
                        {
                            continue;
                        }

                        drawBuffer.SetPixel(x, scanline, Palettes.Palette0[paletteIndex]);
                        pixelDrawn = true;
                        // Once a pixel has been drawn, no need to check other BG's
                        break;
                    }                                        
                    if(pixelDrawn)
                    {
                        break;
                    }
                }

                // If nothing is drawn then default to backdrop colour
                if (pixelDrawn == false)
                {
                    drawBuffer.SetPixel(x, scanline, Palettes.Palette0[0]);
                }
            }
#if ParallelizeScanline
            }); // Parallel.For
            //while (result.IsCompleted == false) ;
#endif
        }