Exemplo n.º 1
0
        private void changeSTATMode(int mode, MMU mmu)
        {
            byte STAT = (byte)(mmu.STAT & ~0x3);

            mmu.STAT = (byte)(STAT | mode);
            //Accessing OAM - Mode 2 (80 cycles)
            if (mode == 2 && isBit(5, STAT))
            { // Bit 5 - Mode 2 OAM Interrupt         (1=Enable) (Read/Write)
                mmu.requestInterrupt(LCD_INTERRUPT);
            }

            //case 3: //Accessing VRAM - Mode 3 (172 cycles) Total M2+M3 = 252 Cycles

            //HBLANK - Mode 0 (204 cycles) Total M2+M3+M0 = 456 Cycles
            else if (mode == 0 && isBit(3, STAT))
            { // Bit 3 - Mode 0 H-Blank Interrupt     (1=Enable) (Read/Write)
                mmu.requestInterrupt(LCD_INTERRUPT);
            }

            //VBLANK - Mode 1 (4560 cycles - 10 lines)
            else if (mode == 1 && isBit(4, STAT))
            { // Bit 4 - Mode 1 V-Blank Interrupt     (1=Enable) (Read/Write)
                mmu.requestInterrupt(LCD_INTERRUPT);
            }
        }
Exemplo n.º 2
0
        public void update(MMU mmu)
        {
            byte JOYP = mmu.JOYP;

            if (!isBit(4, JOYP))
            {
                mmu.JOYP = (byte)((JOYP & 0xF0) | pad);
                if (pad != 0xF)
                {
                    mmu.requestInterrupt(JOYPAD_INTERRUPT);
                }
            }
            if (!isBit(5, JOYP))
            {
                mmu.JOYP = (byte)((JOYP & 0xF0) | buttons);
                if (buttons != 0xF)
                {
                    mmu.requestInterrupt(JOYPAD_INTERRUPT);
                }
            }
            if ((JOYP & 0b00110000) == 0b00110000)
            {
                mmu.JOYP = 0xFF;
            }
        }
Exemplo n.º 3
0
 private void handleDivider(int cycles, MMU mmu)
 {
     divCounter += cycles;
     while (divCounter >= DMG_DIV_FREQ)
     {
         mmu.DIV++;
         divCounter -= DMG_DIV_FREQ;
     }
 }
Exemplo n.º 4
0
        private void drawScanLine(MMU mmu)
        {
            byte LCDC = mmu.LCDC;

            if (isBit(0, LCDC))
            { //Bit 0 - BG Display (0=Off, 1=On)
                renderBG(mmu);
            }
            if (isBit(1, LCDC))
            { //Bit 1 - OBJ (Sprite) Display Enable
                renderSprites(mmu);
            }
        }
Exemplo n.º 5
0
        public void POWER_ON(string cartName)
        {
            mmu    = new MMU();
            cpu    = new CPU(mmu);
            ppu    = new PPU(window);
            timer  = new TIMER();
            joypad = new JOYPAD();

            mmu.loadGamePak(cartName);

            power_switch = true;

            Task t = Task.Factory.StartNew(EXECUTE, TaskCreationOptions.LongRunning);
        }
Exemplo n.º 6
0
        private void renderBG(MMU mmu)
        {
            byte WX    = (byte)(mmu.WX - 7); //WX needs -7 Offset
            byte WY    = mmu.WY;
            byte LY    = mmu.LY;
            byte LCDC  = mmu.LCDC;
            byte SCY   = mmu.SCY;
            byte SCX   = mmu.SCX;
            byte BGP   = mmu.BGP;
            bool isWin = isWindow(LCDC, WY, LY);

            byte y        = isWin ? (byte)(LY - WY) : (byte)(LY + SCY);
            byte tileLine = (byte)((y & 7) * 2);

            ushort tileRow = (ushort)(y / 8 * 32);
            ushort tileMap = isWin ? getWindowTileMapAdress(LCDC) : getBGTileMapAdress(LCDC);

            byte hi = 0;
            byte lo = 0;

            for (int p = 0; p < SCREEN_WIDTH; p++)
            {
                byte x = isWin && p >= WX ? (byte)(p - WX) : (byte)(p + SCX);
                if ((p & 0x7) == 0 || ((p + SCX) & 0x7) == 0)
                {
                    ushort tileCol    = (ushort)(x / 8);
                    ushort tileAdress = (ushort)(tileMap + tileRow + tileCol);

                    ushort tileLoc;
                    if (isSignedAdress(LCDC))
                    {
                        tileLoc = (ushort)(getTileDataAdress(LCDC) + mmu.readVRAM(tileAdress) * 16);
                    }
                    else
                    {
                        tileLoc = (ushort)(getTileDataAdress(LCDC) + ((sbyte)mmu.readVRAM(tileAdress) + 128) * 16);
                    }

                    lo = mmu.readVRAM((ushort)(tileLoc + tileLine));
                    hi = mmu.readVRAM((ushort)(tileLoc + tileLine + 1));
                }

                int colorBit = 7 - (x & 7); //inversed
                int colorId  = GetColorIdBits(colorBit, lo, hi);
                int colorIdThroughtPalette = GetColorIdThroughtPalette(BGP, colorId);

                bmp.SetPixel(p, LY, color[colorIdThroughtPalette]);
            }
        }
Exemplo n.º 7
0
 private void handleTimer(int cycles, MMU mmu)
 {
     if (mmu.TAC_ENABLED)
     {
         timerCounter += cycles;
         while (timerCounter >= TAC_FREQ[mmu.TAC_FREQ])
         {
             mmu.TIMA++;
             timerCounter -= TAC_FREQ[mmu.TAC_FREQ];
         }
         if (mmu.TIMA == 0xFF)
         {
             mmu.requestInterrupt(TIMER_INTERRUPT);
             mmu.TIMA = mmu.TMA;
         }
     }
 }
Exemplo n.º 8
0
        private void renderSprites(MMU mmu)
        {
            byte LY   = mmu.LY;
            byte LCDC = mmu.LCDC;

            for (int i = 0x9C; i >= 0; i -= 4)
            {                                       //0x9F OAM Size, 40 Sprites x 4 bytes:
                int  y    = mmu.readOAM(i) - 16;    //Byte0 - Y Position //needs 16 offset
                int  x    = mmu.readOAM(i + 1) - 8; //Byte1 - X Position //needs 8 offset
                byte tile = mmu.readOAM(i + 2);     //Byte2 - Tile/Pattern Number
                byte attr = mmu.readOAM(i + 3);     //Byte3 - Attributes/Flags

                if ((LY >= y) && (LY < (y + spriteSize(LCDC))))
                {
                    byte palette = isBit(4, attr) ? mmu.OBP1 : mmu.OBP0; //Bit4   Palette number  **Non CGB Mode Only** (0=OBP0, 1=OBP1)

                    int tileRow = isYFlipped(attr) ? spriteSize(LCDC) - 1 - (LY - y) : (LY - y);

                    ushort tileddress = (ushort)(0x8000 + (tile * 16) + (tileRow * 2));
                    byte   lo         = mmu.readVRAM(tileddress);
                    byte   hi         = mmu.readVRAM((ushort)(tileddress + 1));

                    for (int p = 0; p < 8; p++)
                    {
                        int IdPos   = isXFlipped(attr) ? p : 7 - p;
                        int colorId = GetColorIdBits(IdPos, lo, hi);
                        int colorIdThroughtPalette = GetColorIdThroughtPalette(palette, colorId);

                        if ((x + p) >= 0 && (x + p) < SCREEN_WIDTH)
                        {
                            if (!isTransparent(colorId) && (isAboveBG(attr) || isBGWhite(mmu.BGP, x + p, LY)))
                            {
                                bmp.SetPixel(x + p, LY, color[colorIdThroughtPalette]);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 9
0
        public void update(int cycles, MMU mmu)
        {
            scanlineCounter += cycles;
            byte currentMode = (byte)(mmu.STAT & 0x3); //Current Mode Mask

            if (isLCDEnabled(mmu.LCDC))
            {
                switch (currentMode)
                {
                case 2:     //Accessing OAM - Mode 2 (80 cycles)
                    if (scanlineCounter >= OAM_CYCLES)
                    {
                        changeSTATMode(3, mmu);
                        scanlineCounter -= OAM_CYCLES;
                    }
                    break;

                case 3:     //Accessing VRAM - Mode 3 (172 cycles) Total M2+M3 = 252 Cycles
                    if (scanlineCounter >= VRAM_CYCLES)
                    {
                        changeSTATMode(0, mmu);
                        drawScanLine(mmu);
                        scanlineCounter -= VRAM_CYCLES;
                    }
                    break;

                case 0:     //HBLANK - Mode 0 (204 cycles) Total M2+M3+M0 = 456 Cycles
                    if (scanlineCounter >= HBLANK_CYCLES)
                    {
                        mmu.LY++;
                        scanlineCounter -= HBLANK_CYCLES;

                        if (mmu.LY == SCREEN_HEIGHT)
                        {     //check if we arrived Vblank
                            changeSTATMode(1, mmu);
                            mmu.requestInterrupt(VBLANK_INTERRUPT);
                            RenderFrame();
                        }
                        else
                        {     //not arrived yet so return to 2
                            changeSTATMode(2, mmu);
                        }
                    }
                    break;

                case 1:     //VBLANK - Mode 1 (4560 cycles - 10 lines)
                    if (scanlineCounter >= SCANLINE_CYCLES)
                    {
                        mmu.LY++;
                        scanlineCounter -= SCANLINE_CYCLES;

                        if (mmu.LY > SCREEN_VBLANK_HEIGHT)
                        {     //check end of VBLANK
                            changeSTATMode(2, mmu);
                            mmu.LY = 0;
                        }
                    }
                    break;
                }

                if (mmu.LY == mmu.LYC)
                { //handle coincidence Flag
                    mmu.STAT = bitSet(2, mmu.STAT);
                    if (isBit(6, mmu.STAT))
                    {
                        mmu.requestInterrupt(LCD_INTERRUPT);
                    }
                }
                else
                {
                    mmu.STAT = bitClear(2, mmu.STAT);
                }
            }
            else
            { //LCD Disabled
                scanlineCounter = 0;
                mmu.LY          = 0;
                mmu.STAT        = (byte)(mmu.STAT & ~0x3);
            }
        }
Exemplo n.º 10
0
 public void update(int cycles, MMU mmu)
 {
     handleDivider(cycles, mmu);
     handleTimer(cycles, mmu);
 }