예제 #1
0
        private void UpdateModel(bool updateBitmap)
        {
            if (updateBitmap)
            {
                uint[,] backgroundBuffer = x80.backgroundBuffer;
                uint[,] windowBuffer     = x80.windowBuffer;
                byte[] oam = x80.oam;

                for (int y = 0, pixelIndex = 0; y < HEIGHT; ++y)
                {
                    x80.ly       = y;
                    x80.lcdcMode = LcdcModeType.SearchingOamRam;
                    if (x80.lcdcInterruptEnabled &&
                        (x80.lcdcOamInterruptEnabled ||
                         (x80.lcdcLycLyCoincidenceInterruptEnabled && x80.lyCompare == y)))
                    {
                        x80.lcdcInterruptRequested = true;
                    }
                    ExecuteProcessor(800);
                    x80.lcdcMode = LcdcModeType.TransferingData;
                    ExecuteProcessor(1720);

                    x80.UpdateWindow();
                    x80.UpdateBackground();
                    x80.UpdateSpriteTiles();

                    bool backgroundDisplayed = x80.backgroundDisplayed;
                    int  scrollX             = x80.scrollX;
                    int  scrollY             = x80.scrollY;
                    bool windowDisplayed     = x80.windowDisplayed;
                    int  windowX             = x80.windowX - 7;
                    int  windowY             = x80.windowY;

                    for (int x = 0; x < WIDTH; ++x, ++pixelIndex)
                    {
                        uint intensity = 0;

                        if (backgroundDisplayed)
                        {
                            intensity = backgroundBuffer [0xFF & (scrollY + y), 0xFF & (scrollX + x)];
                        }

                        if (windowDisplayed && y >= windowY && y < windowY + HEIGHT && x >= windowX && x < windowX + WIDTH &&
                            windowX >= -7 && windowX < WIDTH && windowY >= 0 && windowY < HEIGHT)
                        {
                            intensity = windowBuffer [y - windowY, x - windowX];
                        }

                        pixels [pixelIndex] = intensity;
                    }

                    if (x80.spritesDisplayed)
                    {
                        uint[, , ,] spriteTile = x80.spriteTile;
                        if (x80.largeSprites)
                        {
                            for (int address = 0; address < WIDTH; address += 4)
                            {
                                int spriteY = oam [address];
                                int spriteX = oam [address + 1];
                                if (spriteY == 0 || spriteX == 0 || spriteY >= 160 || spriteX >= 168)
                                {
                                    continue;
                                }
                                spriteY -= 16;
                                if (spriteY > y || spriteY + 15 < y)
                                {
                                    continue;
                                }
                                spriteX -= 8;

                                int  spriteTileIndex0 = 0xFE & oam [address + 2];
                                int  spriteTileIndex1 = spriteTileIndex0 | 0x01;
                                int  spriteFlags      = oam [address + 3];
                                bool spritePriority   = (0x80 & spriteFlags) == 0x80;
                                bool spriteYFlipped   = (0x40 & spriteFlags) == 0x40;
                                bool spriteXFlipped   = (0x20 & spriteFlags) == 0x20;
                                int  spritePalette    = (0x10 & spriteFlags) == 0x10 ? 1 : 0;

                                if (spriteYFlipped)
                                {
                                    int temp = spriteTileIndex0;
                                    spriteTileIndex0 = spriteTileIndex1;
                                    spriteTileIndex1 = temp;
                                }

                                int spriteRow = y - spriteY;
                                if (spriteRow >= 0 && spriteRow < 8)
                                {
                                    int screenAddress = (y << 7) + (y << 5) + spriteX;
                                    for (int x = 0; x < 8; ++x, ++screenAddress)
                                    {
                                        int screenX = spriteX + x;
                                        if (screenX >= 0 && screenX < WIDTH)
                                        {
                                            uint color = spriteTile [spriteTileIndex0,
                                                                     spriteYFlipped ? 7 - spriteRow : spriteRow,
                                                                     spriteXFlipped ? 7 - x : x, spritePalette];
                                            if (color > 0)
                                            {
                                                if (spritePriority)
                                                {
                                                    if (pixels [screenAddress] == 0xFFFFFFFF)
                                                    {
                                                        pixels [screenAddress] = color;
                                                    }
                                                }
                                                else
                                                {
                                                    pixels [screenAddress] = color;
                                                }
                                            }
                                        }
                                    }
                                    continue;
                                }

                                spriteY += 8;

                                spriteRow = y - spriteY;
                                if (spriteRow >= 0 && spriteRow < 8)
                                {
                                    int screenAddress = (y << 7) + (y << 5) + spriteX;
                                    for (int x = 0; x < 8; ++x, ++screenAddress)
                                    {
                                        int screenX = spriteX + x;
                                        if (screenX >= 0 && screenX < WIDTH)
                                        {
                                            uint color = spriteTile [spriteTileIndex1,
                                                                     spriteYFlipped ? 7 - spriteRow : spriteRow,
                                                                     spriteXFlipped ? 7 - x : x, spritePalette];
                                            if (color > 0)
                                            {
                                                if (spritePriority)
                                                {
                                                    if (pixels [screenAddress] == 0xFFFFFFFF)
                                                    {
                                                        pixels [screenAddress] = color;
                                                    }
                                                }
                                                else
                                                {
                                                    pixels [screenAddress] = color;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            for (int address = 0; address < WIDTH; address += 4)
                            {
                                int spriteY = oam [address];
                                int spriteX = oam [address + 1];
                                if (spriteY == 0 || spriteX == 0 || spriteY >= 160 || spriteX >= 168)
                                {
                                    continue;
                                }
                                spriteY -= 16;
                                if (spriteY > y || spriteY + 7 < y)
                                {
                                    continue;
                                }
                                spriteX -= 8;

                                int  spriteTileIndex = oam [address + 2];
                                int  spriteFlags     = oam [address + 3];
                                bool spritePriority  = (0x80 & spriteFlags) == 0x80;
                                bool spriteYFlipped  = (0x40 & spriteFlags) == 0x40;
                                bool spriteXFlipped  = (0x20 & spriteFlags) == 0x20;
                                int  spritePalette   = (0x10 & spriteFlags) == 0x10 ? 1 : 0;

                                int spriteRow     = y - spriteY;
                                int screenAddress = (y << 7) + (y << 5) + spriteX;
                                for (int x = 0; x < 8; ++x, ++screenAddress)
                                {
                                    int screenX = spriteX + x;
                                    if (screenX >= 0 && screenX < WIDTH)
                                    {
                                        uint color = spriteTile [spriteTileIndex,
                                                                 spriteYFlipped ? 7 - spriteRow : spriteRow,
                                                                 spriteXFlipped ? 7 - x : x, spritePalette];
                                        if (color > 0)
                                        {
                                            if (spritePriority)
                                            {
                                                if (pixels [screenAddress] == 0xFFFFFFFF)
                                                {
                                                    pixels [screenAddress] = color;
                                                }
                                            }
                                            else
                                            {
                                                pixels [screenAddress] = color;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    x80.lcdcMode = LcdcModeType.HBlank;
                    if (x80.lcdcInterruptEnabled && x80.lcdcHBlankInterruptEnabled)
                    {
                        x80.lcdcInterruptRequested = true;
                    }
                    ExecuteProcessor(2040);
                    AddTicksPerScanLine();
                }
            }
            else
            {
                for (int y = 0; y < HEIGHT; ++y)
                {
                    x80.ly       = y;
                    x80.lcdcMode = LcdcModeType.SearchingOamRam;
                    if (x80.lcdcInterruptEnabled &&
                        (x80.lcdcOamInterruptEnabled ||
                         (x80.lcdcLycLyCoincidenceInterruptEnabled && x80.lyCompare == y)))
                    {
                        x80.lcdcInterruptRequested = true;
                    }
                    ExecuteProcessor(800);
                    x80.lcdcMode = LcdcModeType.TransferingData;
                    ExecuteProcessor(1720);
                    x80.lcdcMode = LcdcModeType.HBlank;
                    if (x80.lcdcInterruptEnabled && x80.lcdcHBlankInterruptEnabled)
                    {
                        x80.lcdcInterruptRequested = true;
                    }
                    ExecuteProcessor(2040);
                    AddTicksPerScanLine();
                }
            }

            x80.lcdcMode = LcdcModeType.VBlank;
            if (x80.vBlankInterruptEnabled)
            {
                x80.vBlankInterruptRequested = true;
            }
            if (x80.lcdcInterruptEnabled && x80.lcdcVBlankInterruptEnabled)
            {
                x80.lcdcInterruptRequested = true;
            }
            for (int y = 144; y <= 153; ++y)
            {
                x80.ly = y;
                if (x80.lcdcInterruptEnabled && x80.lcdcLycLyCoincidenceInterruptEnabled &&
                    x80.lyCompare == y)
                {
                    x80.lcdcInterruptRequested = true;
                }
                ExecuteProcessor(4560);
                AddTicksPerScanLine();
            }

            if (Audio != null)
            {
                x80.SoundChip.OutputSound(Audio);
            }
        }
예제 #2
0
        private void UpdateModel(bool updateBitmap)
        {
            if (updateBitmap)
            {
                uint[] backgroundPalette = _x80.BackgroundPalette;
                uint[] objectPalette0    = _x80.ObjectPalette0;
                uint[] objectPalette1    = _x80.ObjectPalette1;
                uint[,] backgroundBuffer = _x80.BackgroundBuffer;
                uint[,] windowBuffer     = _x80.WindowBuffer;
                byte[] oam = _x80.Oam;

                for (int y = 0, pixelIndex = 0; y < 144; y++)
                {
                    _x80.Ly       = y;
                    _x80.LcdcMode = LcdcModeType.SearchingOamRam;
                    if (_x80.LcdcInterruptEnabled &&
                        (_x80.LcdcOamInterruptEnabled ||
                         (_x80.LcdcLycLyCoincidenceInterruptEnabled && _x80.LyCompare == y)))
                    {
                        _x80.LcdcInterruptRequested = true;
                    }
                    ExecuteProcessor(800);
                    _x80.LcdcMode = LcdcModeType.TransferingData;
                    ExecuteProcessor(1720);

                    _x80.UpdateWindow();
                    _x80.UpdateBackground();
                    _x80.UpdateSpriteTiles();

                    bool backgroundDisplayed = _x80.BackgroundDisplayed;
                    bool backgroundAndWindowTileDataSelect = _x80.BackgroundAndWindowTileDataSelect;
                    bool backgroundTileMapDisplaySelect    = _x80.BackgroundTileMapDisplaySelect;
                    int  scrollX                    = _x80.ScrollX;
                    int  scrollY                    = _x80.ScrollY;
                    bool windowDisplayed            = _x80.WindowDisplayed;
                    bool windowTileMapDisplaySelect = _x80.WindowTileMapDisplaySelect;
                    int  windowX                    = _x80.WindowX - 7;
                    int  windowY                    = _x80.WindowY;

                    int windowPointY = windowY + y;

                    for (int x = 0; x < 160; x++, pixelIndex++)
                    {
                        uint intensity = 0;

                        if (backgroundDisplayed)
                        {
                            intensity = backgroundBuffer[0xFF & (scrollY + y), 0xFF & (scrollX + x)];
                        }

                        if (windowDisplayed && y >= windowY && y < windowY + 144 && x >= windowX && x < windowX + 160 &&
                            windowX >= -7 && windowX <= 159 && windowY >= 0 && windowY <= 143)
                        {
                            intensity = windowBuffer[y - windowY, x - windowX];
                        }

                        _pixels[pixelIndex] = intensity;
                    }

                    if (_x80.SpritesDisplayed)
                    {
                        uint[,,,] spriteTile = _x80.SpriteTile;
                        if (_x80.LargeSprites)
                        {
                            for (int address = 0; address < 160; address += 4)
                            {
                                int spriteY = oam[address];
                                int spriteX = oam[address + 1];
                                if (spriteY == 0 || spriteX == 0 || spriteY >= 160 || spriteX >= 168)
                                {
                                    continue;
                                }
                                spriteY -= 16;
                                if (spriteY > y || spriteY + 15 < y)
                                {
                                    continue;
                                }
                                spriteX -= 8;

                                int  spriteTileIndex0 = 0xFE & oam[address + 2];
                                int  spriteTileIndex1 = spriteTileIndex0 | 0x01;
                                int  spriteFlags      = oam[address + 3];
                                bool spritePriority   = (0x80 & spriteFlags) == 0x80;
                                bool spriteYFlipped   = (0x40 & spriteFlags) == 0x40;
                                bool spriteXFlipped   = (0x20 & spriteFlags) == 0x20;
                                int  spritePalette    = (0x10 & spriteFlags) == 0x10 ? 1 : 0;

                                if (spriteYFlipped)
                                {
                                    int temp = spriteTileIndex0;
                                    spriteTileIndex0 = spriteTileIndex1;
                                    spriteTileIndex1 = temp;
                                }

                                int spriteRow = y - spriteY;
                                if (spriteRow >= 0 && spriteRow < 8)
                                {
                                    int screenAddress = (y << 7) + (y << 5) + spriteX;
                                    for (int x = 0; x < 8; x++, screenAddress++)
                                    {
                                        int screenX = spriteX + x;
                                        if (screenX >= 0 && screenX < 160)
                                        {
                                            uint color = spriteTile[spriteTileIndex0,
                                                                    spriteYFlipped ? 7 - spriteRow : spriteRow,
                                                                    spriteXFlipped ? 7 - x : x, spritePalette];
                                            if (color > 0)
                                            {
                                                if (spritePriority)
                                                {
                                                    if (_pixels[screenAddress] == 0xFFFFFFFF)
                                                    {
                                                        _pixels[screenAddress] = color;
                                                    }
                                                }
                                                else
                                                {
                                                    _pixels[screenAddress] = color;
                                                }
                                            }
                                        }
                                    }
                                    continue;
                                }

                                spriteY += 8;

                                spriteRow = y - spriteY;
                                if (spriteRow >= 0 && spriteRow < 8)
                                {
                                    int screenAddress = (y << 7) + (y << 5) + spriteX;
                                    for (int x = 0; x < 8; x++, screenAddress++)
                                    {
                                        int screenX = spriteX + x;
                                        if (screenX >= 0 && screenX < 160)
                                        {
                                            uint color = spriteTile[spriteTileIndex1,
                                                                    spriteYFlipped ? 7 - spriteRow : spriteRow,
                                                                    spriteXFlipped ? 7 - x : x, spritePalette];
                                            if (color > 0)
                                            {
                                                if (spritePriority)
                                                {
                                                    if (_pixels[screenAddress] == 0xFFFFFFFF)
                                                    {
                                                        _pixels[screenAddress] = color;
                                                    }
                                                }
                                                else
                                                {
                                                    _pixels[screenAddress] = color;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            for (int address = 0; address < 160; address += 4)
                            {
                                int spriteY = oam[address];
                                int spriteX = oam[address + 1];
                                if (spriteY == 0 || spriteX == 0 || spriteY >= 160 || spriteX >= 168)
                                {
                                    continue;
                                }
                                spriteY -= 16;
                                if (spriteY > y || spriteY + 7 < y)
                                {
                                    continue;
                                }
                                spriteX -= 8;

                                int  spriteTileIndex = oam[address + 2];
                                int  spriteFlags     = oam[address + 3];
                                bool spritePriority  = (0x80 & spriteFlags) == 0x80;
                                bool spriteYFlipped  = (0x40 & spriteFlags) == 0x40;
                                bool spriteXFlipped  = (0x20 & spriteFlags) == 0x20;
                                int  spritePalette   = (0x10 & spriteFlags) == 0x10 ? 1 : 0;

                                int spriteRow     = y - spriteY;
                                int screenAddress = (y << 7) + (y << 5) + spriteX;
                                for (int x = 0; x < 8; x++, screenAddress++)
                                {
                                    int screenX = spriteX + x;
                                    if (screenX >= 0 && screenX < 160)
                                    {
                                        uint color = spriteTile[spriteTileIndex,
                                                                spriteYFlipped ? 7 - spriteRow : spriteRow,
                                                                spriteXFlipped ? 7 - x : x, spritePalette];
                                        if (color > 0)
                                        {
                                            if (spritePriority)
                                            {
                                                if (_pixels[screenAddress] == 0xFFFFFFFF)
                                                {
                                                    _pixels[screenAddress] = color;
                                                }
                                            }
                                            else
                                            {
                                                _pixels[screenAddress] = color;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    _x80.LcdcMode = LcdcModeType.HBlank;
                    if (_x80.LcdcInterruptEnabled && _x80.LcdcHBlankInterruptEnabled)
                    {
                        _x80.LcdcInterruptRequested = true;
                    }
                    ExecuteProcessor(2040);
                    AddTicksPerScanLine();
                }
            }
            else
            {
                for (int y = 0; y < 144; y++)
                {
                    _x80.Ly       = y;
                    _x80.LcdcMode = LcdcModeType.SearchingOamRam;
                    if (_x80.LcdcInterruptEnabled &&
                        (_x80.LcdcOamInterruptEnabled ||
                         (_x80.LcdcLycLyCoincidenceInterruptEnabled && _x80.LyCompare == y)))
                    {
                        _x80.LcdcInterruptRequested = true;
                    }
                    ExecuteProcessor(800);
                    _x80.LcdcMode = LcdcModeType.TransferingData;
                    ExecuteProcessor(1720);
                    _x80.LcdcMode = LcdcModeType.HBlank;
                    if (_x80.LcdcInterruptEnabled && _x80.LcdcHBlankInterruptEnabled)
                    {
                        _x80.LcdcInterruptRequested = true;
                    }
                    ExecuteProcessor(2040);
                    AddTicksPerScanLine();
                }
            }

            _x80.LcdcMode = LcdcModeType.VBlank;
            if (_x80.VBlankInterruptEnabled)
            {
                _x80.VBlankInterruptRequested = true;
            }
            if (_x80.LcdcInterruptEnabled && _x80.LcdcVBlankInterruptEnabled)
            {
                _x80.LcdcInterruptRequested = true;
            }
            for (int y = 144; y <= 153; y++)
            {
                _x80.Ly = y;
                if (_x80.LcdcInterruptEnabled && _x80.LcdcLycLyCoincidenceInterruptEnabled &&
                    _x80.LyCompare == y)
                {
                    _x80.LcdcInterruptRequested = true;
                }
                ExecuteProcessor(4560);
                AddTicksPerScanLine();
            }
        }