if(register_STAT & 0x20) gbInterrupt |= 2; register_LY = 0;
if(!(register_STAT & 0x40) || (register_LY != register_LYC)) { if((register_STAT & 0x28) == 0x20) gbInterrupt |= 2; }
void gbEmulate(int ticksToStop){  gbRegister tempRegister;  u8 tempValue;  s8 offset;    int clockTicks = 0;  register int opcode = 0;    while(1) {#ifndef FINAL_VERSION    if(systemDebug) {      if(!(IFF & 0x80)) {        if(systemDebug > 1) {          sprintf(gbBuffer,"PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n",                   PC.W, AF.W, BC.W, DE.W,HL.W,SP.W,IFF);        } else {          sprintf(gbBuffer,"PC=%04x I=%02x\n", PC.W, IFF);        }        log(gbBuffer);      }    }#endif    if(IFF & 0x80) {      if(register_LCDC & 0x80) {        clockTicks = gbLcdTicks;      } else        clockTicks = 100;      if(gbLcdMode == 1 && (gbLcdLYIncrementTicks < clockTicks))        clockTicks = gbLcdLYIncrementTicks;      if(gbSerialOn && (gbSerialTicks < clockTicks))        clockTicks = gbSerialTicks;      if(gbTimerOn && (gbTimerTicks < clockTicks))        clockTicks = gbTimerTicks;      if(soundTicks && (soundTicks < clockTicks))        clockTicks = soundTicks;    } else {      opcode = gbReadOpcode(PC.W++);            if(IFF & 0x100) {        IFF &= 0xff;        PC.W--;      }            clockTicks = gbCycles[opcode];            switch(opcode) {      case 0xCB:        // extended opcode        opcode = gbReadOpcode(PC.W++);        clockTicks = gbCyclesCB[opcode];        switch(opcode) {#include "gbCodesCB.h"        }        break;#include "gbCodes.h"          }    }    if(!emulating)      return;    if(gbSgbMode) {      if(gbSgbPacketTimeout) {        gbSgbPacketTimeout -= clockTicks;                if(gbSgbPacketTimeout <= 0)          gbSgbResetPacketState();      }    }        ticksToStop -= clockTicks;        // DIV register emulation    gbDivTicks -= clockTicks;    while(gbDivTicks <= 0) {      register_DIV++;      gbDivTicks += GBDIV_CLOCK_TICKS;    }    if(register_LCDC & 0x80) {      // LCD stuff      gbLcdTicks -= clockTicks;      if(gbLcdMode == 1) {        // during V-BLANK,we need to increment LY at the same rate!        gbLcdLYIncrementTicks -= clockTicks;        while(gbLcdLYIncrementTicks <= 0) {          gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS;          if(register_LY < 153) {            register_LY++;                        if(register_LY >= 153)              gbLcdLYIncrementTicks = 6;          } else {            register_LY = 0x00;            gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS * 2;          }                    // LYC == LY?          gbCompareLYToLYC();        }      }            // our counter is off, see what we need to do      while(gbLcdTicks <= 0) {        int framesToSkip = systemFrameSkip;        if(speedup)          framesToSkip = 9; // try 6 FPS during speedup        switch(gbLcdMode) {        case 0:          // H-Blank          register_LY++;          gbCompareLYToLYC();                    // check if we reached the V-Blank period                 if(register_LY == 144) {            // Yes, V-Blank            // set the LY increment counter            gbLcdLYIncrementTicks = gbLcdTicks + GBLY_INCREMENT_CLOCK_TICKS;            gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS;            gbLcdMode = 1;            if(register_LCDC & 0x80) {              gbInterrupt |= 1; // V-Blank interrupt              gbInterruptWait = 2;              if(register_STAT & 0x10)                gbInterrupt |= 2;            }            gbWindowLine = -1;            gbFrameCount++;            systemFrame();            if((gbFrameCount % 10) == 0)              system10Frames(60);            if(gbFrameCount >= 60) {              u32 currentTime = systemGetClock();              if(currentTime != gbLastTime)                systemShowSpeed(100000/(currentTime - gbLastTime));              else                systemShowSpeed(0);              gbLastTime = currentTime;              gbFrameCount = 0;                   }            u32 joy = 0;            if(systemReadJoypads())              // read default joystick              joy = systemReadJoypad(-1);            gbJoymask = joy;            int newmask = gbJoymask & 255;            if(gbRom[0x147] == 0x22) {              systemUpdateMotionSensor();            }                        if(newmask) {              gbInterrupt |= 16;            }            newmask = (joy >> 10);                        speedup = (newmask & 1) ? true : false;            gbCapture = (newmask & 2) ? true : false;            if(gbCapture && !gbCapturePrevious) {              gbCaptureNumber++;              systemScreenCapture(gbCaptureNumber);            }            gbCapturePrevious = gbCapture;                        if(gbFrameSkipCount >= framesToSkip) {              systemDrawScreen();              gbFrameSkipCount = 0;            } else              gbFrameSkipCount++;          } else {            // go the the OAM being accessed mode            gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;            gbLcdMode = 2;            if(register_STAT & 0x20)              gbInterrupt |= 2;          }          break;        case 1:          // V-Blank          // next mode is OAM being accessed mode          gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;          gbLcdMode = 2;          if(register_STAT & 0x20)            gbInterrupt |= 2;          register_LY = 0;          //      compareLYToLYC();          break;        case 2:          // OAM being accessed mode                    // next mode is OAM and VRAM in use          gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS;          gbLcdMode = 3;          if(register_LY < 144) {            if(!gbSgbMask) {              if(gbFrameSkipCount >= framesToSkip) {                gbRenderLine();                gbDrawSprites();                                switch(systemColorDepth) {                case 16:                  {                    u16 * dest = (u16 *)pix +                      (gbBorderLineSkip+2) * (register_LY + gbBorderRowSkip+1)                      + gbBorderColumnSkip;                    for(int x = 0; x < 160; ) {                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                                            *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                                            *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                                            *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                      *dest++ = systemColorMap16[gbLineMix[x++]];                    }                    if(gbBorderOn)                      dest += gbBorderColumnSkip;                    *dest++ = 0; // for filters that read one pixel more                  }                  break;                case 24:                  {                    u8 *dest = (u8 *)pix +                      3*(gbBorderLineSkip * (register_LY + gbBorderRowSkip) +                         gbBorderColumnSkip);                    for(int x = 0; x < 160;) {                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                      *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];                      dest+= 3;                    }                  }                  break;                case 32:                  {                    u32 * dest = (u32 *)pix +                      (gbBorderLineSkip+1) * (register_LY + gbBorderRowSkip+1)                      + gbBorderColumnSkip;                    for(int x = 0; x < 160;) {                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                                            *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                      *dest++ = systemColorMap32[gbLineMix[x++]];                    }                  }                }                break;              }            }          }          break;        case 3:          // OAM and VRAM in use          // next mode is H-Blank          gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS;          gbLcdMode = 0;          if(register_STAT & 0x08)            gbInterrupt |= 2;          if(gbHdmaOn) {            gbDoHdma();          }          break;        }        // mark the correct lcd mode on STAT register        register_STAT = (register_STAT & 0xfc) | gbLcdMode;      }    }    // serial emulation    if(gbSerialOn) {#ifdef LINK_EMULATION      if(linkConnected) {        gbSerialTicks -= clockTicks;        while(gbSerialTicks <= 0) {          // increment number of shifted bits          gbSerialBits++;          linkProc();          if(gbSerialOn && (gbMemory[0xff02] & 1)) {            if(gbSerialBits == 8) {              gbSerialBits = 0;              gbMemory[0xff01] = 0xff;              gbMemory[0xff02] &= 0x7f;              gbSerialOn = 0;              gbInterrupt |= 8;              gbSerialTicks = 0;            }          }          gbSerialTicks += GBSERIAL_CLOCK_TICKS;        }      } else {#endif        if(gbMemory[0xff02] & 1) {          gbSerialTicks -= clockTicks;                    // overflow          while(gbSerialTicks <= 0) {            // shift serial byte to right and put a 1 bit in its place            //      gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);            // increment number of shifted bits            gbSerialBits++;            if(gbSerialBits == 8) {              // end of transmission              if(gbSerialFunction) // external device                gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]);              else                gbMemory[0xff01] = 0xff;              gbSerialTicks = 0;              gbMemory[0xff02] &= 0x7f;              gbSerialOn = 0;              gbInterrupt |= 8;              gbSerialBits  = 0;            } else              gbSerialTicks += GBSERIAL_CLOCK_TICKS;          }        }#ifdef LINK_EMULATION      }#endif    }        // timer emulation    if(gbTimerOn) {      gbTimerTicks -= clockTicks;            while(gbTimerTicks <= 0) {        register_TIMA++;                if(register_TIMA == 0) {          // timer overflow!                      // reload timer modulo          register_TIMA = register_TMA;                      // flag interrupt          gbInterrupt |= 4;        }                  gbTimerTicks += gbTimerClockTicks;      }    }    /*    if(soundOffFlag) {      if(synchronize && !speedup) {        synchronizeTicks -= clockTicks;                while(synchronizeTicks < 0) {          synchronizeTicks += SYNCHRONIZE_CLOCK_TICKS;                    DWORD now = timeGetTime();          gbElapsedTime += (now - timeNow);                    if(gbElapsedTime < 50) {            DWORD diff = 50 - gbElapsedTime;            Sleep(diff);            timeNow = timeGetTime();            elapsedTime = timeNow - now - diff;            if((int)elapsedTime < 0)              elapsedTime = 0;          } else {            timeNow = timeGetTime();            elapsedTime = 0;          }        }      }    }    */    soundTicks -= clockTicks;    while(soundTicks < 0) {      soundTicks += SOUND_CLOCK_TICKS;      gbSoundTick();    }        register_IF = gbInterrupt;    if(IFF & 0x20) {      IFF &= 0xdf;      IFF |= 0x01;      gbInterruptWait = 0;    } else if(gbInterrupt) {      if(gbInterruptWait == 0) {        gbInterruptWait = 0;        if(IFF & 0x01) {          if((gbInterrupt & 1) && (register_IE & 1)) {            gbVblank_interrupt();            continue;          }                    if((gbInterrupt & 2) && (register_IE & 2)) {            gbLcd_interrupt();            continue;          }                    if((gbInterrupt & 4) && (register_IE & 4)) {            gbTimer_interrupt();            continue;          }                    if((gbInterrupt & 8) && (register_IE & 8)) {            gbSerial_interrupt();            continue;          }          if((gbInterrupt & 16) && (register_IE & 16)) {            gbJoypad_interrupt();            continue;          }        }      } else {        gbInterruptWait -= clockTicks;        if(gbInterruptWait < 0)          gbInterruptWait = 0;      }    }    if(ticksToStop <= 0) {      if(!(register_LCDC & 0x80)) {        if(systemReadJoypads())          gbJoymask = systemReadJoypad(-1);      }      return;    }  }}