Beispiel #1
0
        public LcdController(GameboyAdvance gba)
        {
            this.gba = gba;


            frameBuffer0 = new DirectBitmap(Screen_X_Resolution, Screen_Y_Resolution);
            frameBuffer1 = new DirectBitmap(Screen_X_Resolution, Screen_Y_Resolution);
            FrameBuffer = frameBuffer0;
            drawBuffer = frameBuffer1;

            this.Palettes = new Palettes();

            DisplayControlRegister = new DisplayControlRegister(this);
            DispStatRegister = new DisplayStatusRegister(this);
            BgControlRegisters = new BgControlRegister[4];
            Bg = new Background[4];
            for (int i = 0; i < 4; i++)
            {
                BgControlRegisters[i] = new BgControlRegister(this, i);
                Bg[i] = new Background(gba, i, BgControlRegisters[i]);

                priorityObjList[i] = new List<Obj>();
            }

            Obj = new Obj[Max_Sprites];
            for (int i = 0; i < Max_Sprites; i++)
            {
                Obj[i] = new Obj(gba, new ObjAttributes(gba, i * 8, gba.Memory.OamRam));
            }

            OamAffineMatrices = new OamAffineMatrix[Max_OAM_Matrices];
            UInt32 address = 0x00000006;
            for (int i = 0; i < 32; i++)
            {
                OamAffineMatrices[i] = new OamAffineMatrix(gba.Memory.OamRam, address);

                address += 0x20;
            }

            Windows = new Window[4];
            for (int i = 0; i < 4; i++)
            {
                Windows[i] = new Window(gba);
            }

#if THREADED_SCANLINE
            drawScanline = false;
            exitThread = false;
            scanlineThread = new Thread(new ThreadStart(ScanlineThread));
            scanlineThread.Start();
#endif
        }
Beispiel #2
0
        public LcdController(GameboyAdvance gba)
        {
            this.gba = gba;


            frameBuffer0 = new DirectBitmap(Screen_X_Resolution, Screen_Y_Resolution);
            frameBuffer1 = new DirectBitmap(Screen_X_Resolution, Screen_Y_Resolution);
            FrameBuffer = frameBuffer0;
            drawBuffer = frameBuffer1;

            this.Palettes = new Palettes();

            DisplayControlRegister = new DisplayControlRegister(gba, this);
            DispStatRegister = new DisplayStatusRegister(gba, this);
            
            Bg = new Background[4];
            UInt32 scrollBaseAddress = 0x4000010;
            for (int i = 0; i < 4; i++)
            {
                BgControlRegister cntReg = new BgControlRegister(gba, this, i, (UInt32) (0x4000008 + (i * 2)));
                MemoryRegister16 scrollXReg = new MemoryRegister16(gba.Memory, scrollBaseAddress, false, true, 0x01);
                MemoryRegister16 scrollYReg = new MemoryRegister16(gba.Memory, scrollBaseAddress + 2, false, true, 0x01);
                Bg[i] = new Background(gba, i, cntReg, scrollXReg, scrollYReg);

                scrollBaseAddress += 4;
            }

            VCount = new MemoryRegister8(gba.Memory, 0x04000006, true, false);

            this.ObjController = new ObjController(gba);

            Windows = new Window[4];
            Windows[0] = new Window(gba, 0x4000040, 0x4000048);
            Windows[1] = new Window(gba, 0x4000042, 0x4000049);
            Windows[2] = new Window(gba, 0, 0x400004A);
            Windows[3] = new Window(gba, 0, 0x400004B);

            this.BlendControlRegister = new BlendControlRegister(this, gba);
            BlendingCoefficientRegister = new PixelCoefficientRegister(this, gba, 0x4000052);
            BrightnessCoefficientRegister = new PixelCoefficientRegister(this, gba, 0x4000054);

#if THREADED_SCANLINE
            //Interlocked.Exchange(ref drawScanline, 0);
            drawScanline = 0;
            exitThread = false;
            scanlineThread = new Thread(new ThreadStart(ScanlineThread));
            scanlineThread.Priority = ThreadPriority.Highest;
            scanlineThread.Start();
#endif
        }
Beispiel #3
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
        }