Example #1
0
        public void InterruptServiceRoutine()
        {
            byte bIF = Memory.DirectRead(IF);
            byte bIE = Memory.DirectRead(IE);
            int  f   = IRQLookup[bIF & bIE & 0x1F]; //-1 means no interrupt

            if (IME)
            {
                if (f != -1)
                {
                    //2 Internal delays
                    Board.AdvanceSystemTime(); //4
                    Board.AdvanceSystemTime(); //8

                    //PUSH PC
                    Board.AdvanceSystemTime(); //12
                    Memory.Write((byte)(Registers.PC >> 8), --Registers.SP);

                    Board.AdvanceSystemTime(); //16
                    Memory.Write((byte)Registers.PC, --Registers.SP);

                    //SERVE
                    bIF = ServeIRQ(f, bIF);

                    Board.AdvanceSystemTime(); //20
                    Memory.DirectWrite(bIF, IF);

                    if (GetCPU().Halt)
                    {
                        Board.AdvanceSystemTime(); //24
                        GetCPU().Halt = false;
                    }

                    SetIME(false);
                }
            }
            else
            {
                if (f != -1)
                {
                    if (GetCPU().Halt)
                    {
                        Board.AdvanceSystemTime(); //4
                        GetCPU().Halt = false;
                        GetCPU().DoubleInstructionExecutionBug = DoubleInstructionEnable;
                        DoubleInstructionEnable = true;
                    }
                }
                else
                {
                    DoubleInstructionEnable = false;
                }
            }

            if (Schedule)
            {
                IME      = true;
                Schedule = false;
            }
        }
Example #2
0
 public override void Update(int Clocks)
 {
     if (TransferSignal)
     {
         Clock -= Clocks;
         if (Clock <= 0)
         {
             SC &= 0x7F;
             SB  = 0xFF;
             Memory.DirectWrite((byte)(Memory.DirectRead(0xFF0F) | 0x8), 0xFF0F);
             TransferSignal = false;
             Clock          = 4096;
         }
     }
 }
Example #3
0
        /**
         * "It (DIV) works by using an internal system 16 bit counter. The counter increases each clock (4 clocks per
         * nop) and the value of DIV is the 8 upper bits of the counter: it increases every 256 oscillator clocks.
         * The value of DIV is the actual bits of the system internal counter, not a mirror, not a register that
         * increases with the system internal counter: The actual bits of the counter mapped to memory."
         * Source: AntonioND, The Cycle-Accurate Game Boy Docs
         *
         * "The signal used to increase the TIMA register is generated in a weird way. It selects the actual value
         * of one bit of the system internal counter, and performs an and operation with the enable bit in TAC.
         * This means that writing to the DIV register affects the timer too (writing to timer registers doesn't
         * affect the DIV register)."
         * Source: AntonioND, The Cycle-Accurate Game Boy Docs
         *
         * Tima is not blackbox so we can actually implement what Antonio mentions in his Docs about TIMA and indeed:
         * bool TIMASIGNAL = (((DIVREG & MASK) / MASK) & ((TACREG & 4) / 4)) != 0;
         * or to avoid the costly divisions: TIMASIGNAL = (DIV & MASK) == MASK && (TAC & 4) == 4;
         * TIMASIGNAL is true when the circuit is HI. TIMA increases if the FallingEdgeDetector
         * detects a 1 -> 0 transition of TIMASIGNAL.
         */
        public override void Update(int clocks)
        {
            DIV = (ushort)(clocks + DIV);

            bool TIMASIGNAL = (DIV & MASK) == MASK && (TAC & 4) == 4;

            if (ReleaseOverflow)
            {
                //TIME: 8
                Overflowing     = false;
                ReleaseOverflow = false;
            }

            //After the brief period, TIMA will do its regular routine.
            if (Overflowing)
            {
                //TIME: 4
                TIMA = TMA;
                Memory.DirectWrite((byte)(Memory.DirectRead(IF) | 0x4), IF);
                TIMACARRY       = false;
                ReleaseOverflow = true;
            }

            if (FallingEdgeDetector.Check(TIMASIGNAL))
            {
                TIMA++;
                //For a brief period (1 cycle or 4 clocks) TIMA has the value 0, and it's currently overflowing (AntonioND)
                if (TIMA == 0x0 && TIMACARRY)
                {
                    //TIME: 0
                    Overflowing = true;
                }
                else if (TIMA == 0xFF)
                {
                    //about to overflow
                    TIMACARRY = true;
                }
            }
        }
Example #4
0
 private void IRQ(byte BIT)
 {
     Memory.DirectWrite((byte)(Memory.DirectRead(0xFF0F) | BIT), 0xFF0F);
 }