Example #1
0
        public uint[] GetSprite(int index)
        {
            OAM oam = GetOAM(index);

            DrawSprite(_sprite, oam.SpriteCode, 0, 0);
            return(_sprite);
        }
        internal void RefreshSprite(uint[] pixels, OAM oam)
        {
            Utils.TransferBytesToWriteableBitmap(_spriteImage, pixels);
              OnPropertyChanged(() => SpriteImage);

              _spriteData = oam;
              OnPropertyChanged(() => SpriteData);
        }
        internal static void GetSpriteRowPixels(short[] pixelLookupTable,
                       DisplayDefinition disDef, Memory memory, OAM[] spriteOAMs,
                       uint[] targetPixels, uint[] pixelBuffer,
                       int row, bool LCDCBit2,
                       bool ignoreBackgroundPriority = false)
        {
            int scanLineSize = GetScanLineOAMs(disDef, spriteOAMs, row, LCDCBit2);

              // We obtain the pixels we want from it
              for (int oamIndex = scanLineSize - 1; oamIndex >= 0; --oamIndex)
              {
            OAM oam = scanLineOAMs[oamIndex];

            bool flipX = Utils.UtilFuncs.TestBit(oam.Flags, 5) != 0;
            bool flipY = Utils.UtilFuncs.TestBit(oam.Flags, 6) != 0;
            byte[] tilePixels = GetTileData(disDef, memory, 0x8000, oam.SpriteCode,
                                        LCDCBit2, flipX, flipY);

            int x = oam.X - 8;
            int y = row - (oam.Y - 16);

            uint[] spritePallete = (Utils.UtilFuncs.TestBit(oam.Flags, 4) == 0) ?
                                  disDef.SpritePallete0 : disDef.SpritePallete1;

            GetPixelsFromTileBytes(pixelLookupTable,
                               ref pixelBuffer,
                               spritePallete,
                               disDef.PixelPerTileX,
                               tilePixels[2 * y], tilePixels[2 * y + 1]);
            bool backgroundPriority = (Utils.UtilFuncs.TestBit(oam.Flags, 7) != 0);
            if (ignoreBackgroundPriority)
            {
              backgroundPriority = false;
            }
            for (int i = 0; i < 8; ++i)
            {
              int pX = x + i;
              if (pX < 0) { continue; }
              if (pX >= disDef.ScreenPixelCountX) { break; }
              uint color = pixelBuffer[i];
              if (color == 0) { continue; } // transparent pixel

              // NOTE(Cristian): If the BG priority bit is set, the sprite is hidden
              //                 on every color except tile color 0
              if (backgroundPriority)
              {
            if (targetPixels[pX] != disDef.TileColors[0]) { continue; }
              }
              targetPixels[pX] = color;
            }
              }
        }
        /// <summary>
        /// Gets the OAMs for the a certain row
        /// </summary>
        /// <param name="spriteOAMs"></param>
        /// <param name="row"></param>
        /// <param name="LCDCBit2"></param>
        /// <returns></returns>
        internal static int GetScanLineOAMs(DisplayDefinition disDef, OAM[] spriteOAMs, int row, bool LCDCBit2)
        {
            int spriteSize = disDef.BytesPerTileShort / 2;
              if (LCDCBit2) { spriteSize = disDef.BytesPerTileLong / 2; }

              // Then we select the 10 that correspond
              int scanLineSize = 0;
              int maxScanLineSize = 10;
              foreach (OAM oam in spriteOAMs)
              {
            int y = oam.Y - 16;
            if ((y <= row) && (row < (y + spriteSize)))
            {
              scanLineOAMs[scanLineSize++] = oam;
              if (scanLineSize == maxScanLineSize) { break; }
            }
              }

              return scanLineSize;
        }
Example #5
0
        internal void Reset()
        {
            /*** DISPLAY DEFINITION ***/

            _disDef.FramePixelCountX  = 256;
            _disDef.FramePixelCountY  = 256;
            _disDef.ScreenPixelCountX = 160;
            _disDef.ScreenPixelCountY = 144;
            _disDef.TimingPixelCountX = 256;
            _disDef.TimingPixelCountY = 154;
            _disDef.FrameTileCountX   = 32;
            _disDef.FrameTileCountY   = 32;
            _disDef.ScreenTileCountX  = 20;
            _disDef.ScreenTileCountY  = 18;
            _disDef.BytesPerTileShort = 16;
            _disDef.BytesPerTileLong  = 32;
            _disDef.PixelPerTileX     = 8;
            _disDef.PixelPerTileY     = 8;
            _disDef.BytesPerPixel     = 4;
            _disDef.PixelFormat       = PixelFormat.Format32bppArgb;
            // TODO(Cristian): Output the color to the view for custom setting
            _disDef.TileColors = new uint[4]
            {
                0xFFFFFFFF,
                0xFFBBBBBB,
                0xFF666666,
                0xFF000000
            };
            _disDef.TilePallete = new uint[4];
            // TODO(Cristian): Output the color to the view for custom setting
            _disDef.SpriteColors = new uint[4]
            {
                0xFFFFFFFF,
                0xFFBBBBBB,
                0xFF666666,
                0xFF000000
            };
            _disDef.SpritePallete0 = new uint[4];
            _disDef.SpritePallete1 = new uint[4];

            // Tile stargets
            _spriteOAMs = new OAM[_spriteCount];
            for (int i = 0; i < _spriteOAMs.Length; ++i)
            {
                _spriteOAMs[i] = new OAM();
            }

            /*** DISPLAY STATUS ***/

            _state.PrevTickCount        = 0;
            _state.CurrentLineTickCount = 0;
            _state.CurrentLine          = 0;
            // NOTE(Cristian): This are default values when there are no sprites
            //                 They should change on runtime
            _state.OAMSearchTickCount    = 83;
            _state.DataTransferTickCount = 83 + 175;
            _state.TotalLineTickCount    = 456;
            _state.Enabled = true;
            // TODO(Cristian): Find out at what state the display starts!
            _state.DisplayMode = DisplayModes.Mode10;

            _state.TileBase  = true;
            _state.NoTileMap = false;
            _state.TileMap   = false;

            _state.LCDCBits = new bool[8];

            // We start the registers correctly
            HandleMemoryChange(MMR.LCDC, _memory.LowLevelRead((ushort)MMR.LCDC));
            HandleMemoryChange(MMR.LCDC, _memory.LowLevelRead((ushort)MMR.LCDC));
            HandleMemoryChange(MMR.SCY, _memory.LowLevelRead((ushort)MMR.SCY));
            HandleMemoryChange(MMR.SCX, _memory.LowLevelRead((ushort)MMR.SCX));
            HandleMemoryChange(MMR.LYC, _memory.LowLevelRead((ushort)MMR.LYC));
            HandleMemoryChange(MMR.DMA, _memory.LowLevelRead((ushort)MMR.DMA));
            HandleMemoryChange(MMR.BGP, _memory.LowLevelRead((ushort)MMR.BGP));
            HandleMemoryChange(MMR.OBP0, _memory.LowLevelRead((ushort)MMR.OBP0));
            HandleMemoryChange(MMR.OBP1, _memory.LowLevelRead((ushort)MMR.OBP1));
            HandleMemoryChange(MMR.WY, _memory.LowLevelRead((ushort)MMR.WY));
            HandleMemoryChange(MMR.WX, _memory.LowLevelRead((ushort)MMR.WX));

            /*** DRAW TARGETS ***/

            // We create the target bitmaps
            _debugInternalTargets = new uint[Enum.GetNames(typeof(DebugTargets)).Length][];
            _debugExternalTargets = new uint[Enum.GetNames(typeof(DebugTargets)).Length][];
            _updateDebugTargets   = new bool[Enum.GetNames(typeof(DebugTargets)).Length];

            _debugInternalTargets[(int)DebugTargets.Background] = new uint[_disDef.FramePixelCountX * _disDef.FramePixelCountY];
            _debugExternalTargets[(int)DebugTargets.Background] = new uint[_disDef.FramePixelCountX * _disDef.FramePixelCountY];
            _updateDebugTargets[(int)DebugTargets.Background]   = false;

            _debugInternalTargets[(int)DebugTargets.Tiles] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
            _debugExternalTargets[(int)DebugTargets.Tiles] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
            _updateDebugTargets[(int)DebugTargets.Tiles]   = false;

            _debugInternalTargets[(int)DebugTargets.Window] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
            _debugExternalTargets[(int)DebugTargets.Window] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
            _updateDebugTargets[(int)DebugTargets.Window]   = false;

            _debugInternalTargets[(int)DebugTargets.SpriteLayer] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
            _debugExternalTargets[(int)DebugTargets.SpriteLayer] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
            _updateDebugTargets[(int)DebugTargets.SpriteLayer]   = false;

            _debugInternalTargets[(int)DebugTargets.DisplayTiming] = new uint[_disDef.TimingPixelCountX * _disDef.TimingPixelCountY];
            _debugExternalTargets[(int)DebugTargets.DisplayTiming] = new uint[_disDef.TimingPixelCountX * _disDef.TimingPixelCountY];
            _updateDebugTargets[(int)DebugTargets.DisplayTiming]   = false;

            _screenInternalBuffer = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
            _screenExternalBuffer = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
            _sprite = new uint[8 * 16];

            _tempPixelBuffer     = new uint[_disDef.PixelPerTileX];
            _tempFrameLineBuffer = new uint[_disDef.FramePixelCountX];

            // We update the display status info
            UpdateDisplayLineInfo(false);
        }
Example #6
0
        internal void Reset()
        {
            /*** DISPLAY DEFINITION ***/

              _disDef.FramePixelCountX = 256;
              _disDef.FramePixelCountY = 256;
              _disDef.ScreenPixelCountX = 160;
              _disDef.ScreenPixelCountY = 144;
              _disDef.TimingPixelCountX = 256;
              _disDef.TimingPixelCountY = 154;
              _disDef.FrameTileCountX = 32;
              _disDef.FrameTileCountY = 32;
              _disDef.ScreenTileCountX = 20;
              _disDef.ScreenTileCountY = 18;
              _disDef.BytesPerTileShort = 16;
              _disDef.BytesPerTileLong = 32;
              _disDef.PixelPerTileX = 8;
              _disDef.PixelPerTileY = 8;
              _disDef.BytesPerPixel = 4;
              _disDef.PixelFormat = PixelFormat.Format32bppArgb;
              // TODO(Cristian): Output the color to the view for custom setting
              _disDef.TileColors = new uint[4]
              {
            0xFFFFFFFF,
            0xFFBBBBBB,
            0xFF666666,
            0xFF000000
              };
              _disDef.TilePallete = new uint[4];
              // TODO(Cristian): Output the color to the view for custom setting
              _disDef.SpriteColors = new uint[4]
              {
            0xFFFFFFFF,
            0xFFBBBBBB,
            0xFF666666,
            0xFF000000
              };
              _disDef.SpritePallete0 = new uint[4];
              _disDef.SpritePallete1 = new uint[4];

              // Tile stargets
              _spriteOAMs = new OAM[_spriteCount];
              for (int i = 0; i < _spriteOAMs.Length; ++i)
              {
            _spriteOAMs[i] = new OAM();
              }

              /*** DISPLAY STATUS ***/

              _state.PrevTickCount = 0;
              _state.CurrentLineTickCount = 0;
              _state.CurrentLine = 0;
              // NOTE(Cristian): This are default values when there are no sprites
              //                 They should change on runtime
              _state.OAMSearchTickCount = 83;
              _state.DataTransferTickCount = 83 + 175;
              _state.TotalLineTickCount = 456;
              _state.Enabled = true;
              // TODO(Cristian): Find out at what state the display starts!
              _state.DisplayMode = DisplayModes.Mode10;

              _state.TileBase = true;
              _state.NoTileMap = false;
              _state.TileMap = false;

              _state.LCDCBits = new bool[8];

              // We start the registers correctly
              HandleMemoryChange(MMR.LCDC, _memory.LowLevelRead((ushort)MMR.LCDC));
              HandleMemoryChange(MMR.LCDC, _memory.LowLevelRead((ushort)MMR.LCDC));
              HandleMemoryChange(MMR.SCY, _memory.LowLevelRead((ushort)MMR.SCY));
              HandleMemoryChange(MMR.SCX, _memory.LowLevelRead((ushort)MMR.SCX));
              HandleMemoryChange(MMR.LYC, _memory.LowLevelRead((ushort)MMR.LYC));
              HandleMemoryChange(MMR.DMA, _memory.LowLevelRead((ushort)MMR.DMA));
              HandleMemoryChange(MMR.BGP, _memory.LowLevelRead((ushort)MMR.BGP));
              HandleMemoryChange(MMR.OBP0, _memory.LowLevelRead((ushort)MMR.OBP0));
              HandleMemoryChange(MMR.OBP1, _memory.LowLevelRead((ushort)MMR.OBP1));
              HandleMemoryChange(MMR.WY, _memory.LowLevelRead((ushort)MMR.WY));
              HandleMemoryChange(MMR.WX, _memory.LowLevelRead((ushort)MMR.WX));

              /*** DRAW TARGETS ***/

              // We create the target bitmaps
              _debugInternalTargets = new uint[Enum.GetNames(typeof(DebugTargets)).Length][];
              _debugExternalTargets = new uint[Enum.GetNames(typeof(DebugTargets)).Length][];
              _updateDebugTargets = new bool[Enum.GetNames(typeof(DebugTargets)).Length];

              _debugInternalTargets[(int)DebugTargets.Background] = new uint[_disDef.FramePixelCountX * _disDef.FramePixelCountY];
              _debugExternalTargets[(int)DebugTargets.Background] = new uint[_disDef.FramePixelCountX * _disDef.FramePixelCountY];
              _updateDebugTargets[(int)DebugTargets.Background] = false;

              _debugInternalTargets[(int)DebugTargets.Tiles] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
              _debugExternalTargets[(int)DebugTargets.Tiles] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
              _updateDebugTargets[(int)DebugTargets.Tiles] = false;

              _debugInternalTargets[(int)DebugTargets.Window] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
              _debugExternalTargets[(int)DebugTargets.Window] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
              _updateDebugTargets[(int)DebugTargets.Window] = false;

              _debugInternalTargets[(int)DebugTargets.SpriteLayer] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
              _debugExternalTargets[(int)DebugTargets.SpriteLayer] = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
              _updateDebugTargets[(int)DebugTargets.SpriteLayer] = false;

              _debugInternalTargets[(int)DebugTargets.DisplayTiming] = new uint[_disDef.TimingPixelCountX * _disDef.TimingPixelCountY];
              _debugExternalTargets[(int)DebugTargets.DisplayTiming] = new uint[_disDef.TimingPixelCountX * _disDef.TimingPixelCountY];
              _updateDebugTargets[(int)DebugTargets.DisplayTiming] = false;

              _screenInternalBuffer = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
              _screenExternalBuffer = new uint[_disDef.ScreenPixelCountX * _disDef.ScreenPixelCountY];
              _sprite = new uint[8 * 16];

              _tempPixelBuffer = new uint[_disDef.PixelPerTileX];
              _tempFrameLineBuffer = new uint[_disDef.FramePixelCountX];

              // We update the display status info
              UpdateDisplayLineInfo(false);
        }
Example #7
0
        GetSpriteRowPixels(short[] pixelLookupTable,
                           DisplayDefinition disDef, Memory memory, OAM[] spriteOAMs,
                           uint[] targetPixels, uint[] pixelBuffer,
                           int row, bool LCDCBit2,
                           bool ignoreBackgroundPriority = false)
        {
            int scanLineSize = GetScanLineOAMs(disDef, spriteOAMs, row, LCDCBit2);

            // We obtain the pixels we want from it
            for (int oamIndex = scanLineSize - 1; oamIndex >= 0; --oamIndex)
            {
                OAM oam = scanLineOAMs[oamIndex];

                bool   flipX      = Utils.UtilFuncs.TestBit(oam.Flags, 5) != 0;
                bool   flipY      = Utils.UtilFuncs.TestBit(oam.Flags, 6) != 0;
                byte[] tilePixels = GetTileData(disDef, memory, 0x8000, oam.SpriteCode,
                                                LCDCBit2, flipX, flipY);

                int x = oam.X - 8;
                int y = row - (oam.Y - 16);

                uint[] spritePallete = (Utils.UtilFuncs.TestBit(oam.Flags, 4) == 0) ?
                                       disDef.SpritePallete0 : disDef.SpritePallete1;

                GetPixelsFromTileBytes(pixelLookupTable,
                                       ref pixelBuffer,
                                       spritePallete,
                                       disDef.PixelPerTileX,
                                       tilePixels[2 * y], tilePixels[2 * y + 1]);
                bool backgroundPriority = (Utils.UtilFuncs.TestBit(oam.Flags, 7) != 0);
                if (ignoreBackgroundPriority)
                {
                    backgroundPriority = false;
                }
                for (int i = 0; i < 8; ++i)
                {
                    int pX = x + i;
                    if (pX < 0)
                    {
                        continue;
                    }
                    if (pX >= disDef.ScreenPixelCountX)
                    {
                        break;
                    }
                    uint color = pixelBuffer[i];
                    if (color == 0)
                    {
                        continue;
                    }                   // transparent pixel

                    // NOTE(Cristian): If the BG priority bit is set, the sprite is hidden
                    //                 on every color except tile color 0
                    if (backgroundPriority)
                    {
                        if (targetPixels[pX] != disDef.TileColors[0])
                        {
                            continue;
                        }
                    }
                    targetPixels[pX] = color;
                }
            }
        }