コード例 #1
0
void
S9xDoHBlankProcessing_HBLANK_END_EVENT () {
	//START_PROFILE_FUNC (S9xDoHBlankProcessing);			
#ifdef CPU_SHUTDOWN
  CPUPack.CPU.WaitCounter++;
#endif
  if (Settings.SuperFX) S9xSuperFXExec ();
  	  

	cpu_glob_cycles += CPUPack.CPU.Cycles-old_cpu_cycles;		
	CPUPack.CPU.Cycles -= Settings.H_Max;	
	old_cpu_cycles=CPUPack.CPU.Cycles;
	
#ifdef FAST_IAPU_APUEXECUTING_CHECK
	if (IAPU_APUExecuting_Main==false || APUExecuting_Main_Counter==0)
		IAPU_APUExecuting_Main = IAPU_APUExecuting;
	if (IAPU_APUExecuting_Main){
		apu_glob_cycles_Main=cpu_glob_cycles;
		if (cpu_glob_cycles>=0x00700000) {
			APU_EXECUTE2();
		}
	}
	else {
  		apu_glob_cycles=apu_glob_cycles_Main=0;
  		Uncache_APU_Cycles = 0;
	}
	if (APUExecuting_Main_Counter==0){
		FLUSH_APU();
	}
#else
  //(IAPUuncached.NextAPUTimerPos) -= (Settings.H_Max * 10000L);      
  if (  (IAPU_APUExecuting_Main)) {
  	//(APUPack.APU.Cycles) -= Settings.H_Max;
		apu_glob_cycles=cpu_glob_cycles;
#ifdef ME_SOUND		
		if (cpu_glob_cycles>=0x00700000) {		
			APU_EXECUTE2 ();
		}
#else
//		if (cpu_glob_cycles>=0x00000000) {		
//			APU_EXECUTE2 ();
//		}
#endif		
  }
  else {
  	//(APUPack.APU.Cycles) = 0;
  	apu_glob_cycles=0;
  	Uncache_APU_Cycles = 0;
  }
#endif
  
       
  CPUPack.CPU.NextEvent = -1;
// not use
//  CPUPack.ICPU.Scanline++;

  if (++CPUPack.CPU.V_Counter > (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) {
  	//PPU.OAMAddr = PPU.SavedOAMAddr;
    //PPU.OAMFlip = 0;            
    CPUPack.CPU.V_Counter = 0;
    ROM_GLOBAL[0x213F]^=0x80;
    CPUPack.CPU.NMIActive = FALSE;
    //CPUPack.ICPU.Frame++;
    PPU.HVBeamCounterLatched = 0;
    CPUPack.CPU.Flags |= SCAN_KEYS_FLAG;
    S9xStartHDMA ();
  }

  if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPUPack.CPU.V_Counter == PPU.IRQVBeamPos) S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE);
#if (1)
//  pEvent->apu_event1[pEvent->apu_event1_cpt2 & 0xFFFF]=(os9x_apu_ratio != 256) ? cpu_glob_cycles * os9x_apu_ratio / 256: cpu_glob_cycles;
//  pEvent->apu_event1_cpt2++;
  uint32 EventVal = (os9x_apu_ratio != 256) ? cpu_glob_cycles * os9x_apu_ratio / 256: cpu_glob_cycles;
  if (CPUPack.CPU.V_Counter & 1) {
    EventVal |= 0x80000000;
  }
#ifdef ME_SOUND
  int pos=apu_event1_cpt2_main++;
  apu_event1[pos & APU_EVENT_MASK] = EventVal;
  apu_event1_cpt2=apu_event1_cpt2_main;
#else
  int pos=apu_event1_cpt2;
  apu_event1[pos & APU_EVENT_MASK] = EventVal;
  apu_event1_cpt2=pos+1;
#endif

  //APU_EXECUTE2 ();
    
  /*if ((APUPack.APU.TimerEnabled) [2]) {
		(APUPack.APU.Timer) [2] += 4;
		while ((APUPack.APU.Timer) [2] >= (APUPack.APU.TimerTarget) [2]) {
		  (IAPUuncached.RAM) [0xff] = ((IAPUuncached.RAM) [0xff] + 1) & 0xf;
		  (APUPack.APU.Timer) [2] -= (APUPack.APU.TimerTarget) [2];
#ifdef SPC700_SHUTDOWN
		  (IAPUuncached.WaitCounter)++;
		  (IAPU_APUExecuting)= TRUE;
#endif		
		}
	}*/
#else
	if (CPUPack.CPU.V_Counter & 1) {		
		apu_event2[(apu_event2_cpt2)&0xFFFF]=cpu_glob_cycles * os9x_apu_ratio / 256;  
  	(apu_event2_cpt2)++;
		/*if ((APUPack.APU.TimerEnabled) [0]) {
		  (APUPack.APU.Timer) [0]++;
		  if ((APUPack.APU.Timer) [0] >= (APUPack.APU.TimerTarget) [0]) {
				(IAPUuncached.RAM) [0xfd] = ((IAPUuncached.RAM) [0xfd] + 1) & 0xf;
				(APUPack.APU.Timer) [0] = 0;
#ifdef SPC700_SHUTDOWN		
				(IAPUuncached.WaitCounter)++;
				(IAPU_APUExecuting)= TRUE;
#endif		    
		  }
		}
		if ((APUPack.APU.TimerEnabled) [1]) {
		  (APUPack.APU.Timer) [1]++;
		  if ((APUPack.APU.Timer) [1] >= (APUPack.APU.TimerTarget) [1]) {
				(IAPUuncached.RAM) [0xfe] = ((IAPUuncached.RAM) [0xfe] + 1) & 0xf;
				(APUPack.APU.Timer) [1] = 0;
#ifdef SPC700_SHUTDOWN		
				(IAPUuncached.WaitCounter)++;
				(IAPU_APUExecuting) = TRUE;
#endif		    
		  }
		}*/		
	}	  
#endif
  if (CPUPack.CPU.V_Counter == FIRST_VISIBLE_LINE)
    {
      ROM_GLOBAL[0x4210] = 0;
      CPUPack.CPU.Flags &= ~NMI_FLAG;
      S9xStartScreenRefresh ();
    }
  if (CPUPack.CPU.V_Counter >= FIRST_VISIBLE_LINE &&
      CPUPack.CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE)
    {
      RenderLine (CPUPack.CPU.V_Counter - FIRST_VISIBLE_LINE);
      S9xReschedule ();                  
  		//FINISH_PROFILE_FUNC (S9xDoHBlankProcessing); 
  		return;
    }

  if (CPUPack.CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
    {
      // Start of V-blank
      S9xEndScreenRefresh ();
      //PPU.FirstSprite = 0;
      IPPU.HDMA = 0;
      // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
#ifdef DEBUGGER
	  missing.dma_this_frame = 0;
#endif
	  IPPU.MaxBrightness = PPU.Brightness;
      PPU.ForcedBlanking = (ROM_GLOBAL[0x2100] >> 7) & 1;
      
      if(!PPU.ForcedBlanking){
				PPU.OAMAddr = PPU.SavedOAMAddr;			
				uint8 tmp = 0;
				if(PPU.OAMPriorityRotation)
					tmp = (PPU.OAMAddr&0xFE)>>1;
				if((PPU.OAMFlip&1) || PPU.FirstSprite!=tmp){
					PPU.FirstSprite=tmp;
					IPPU.OBJChanged=TRUE;
				}			
				PPU.OAMFlip = 0;
			}
コード例 #2
0
ファイル: cpuexec.cpp プロジェクト: joshdekock/jim-pspware
void S9xDoHBlankProcessing ()
{
#ifdef CPU_SHUTDOWN
    CPU.WaitCounter++;
#endif
    switch (CPU.WhichEvent)
    {
    case HBLANK_START_EVENT:
	if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
	    IPPU.HDMA = S9xDoHDMA (IPPU.HDMA);

	break;

    case HBLANK_END_EVENT:
	S9xSuperFXExec ();

#ifndef STORM
	if (Settings.SoundSync)
	    S9xGenerateSound ();
#endif

	CPU.Cycles -= Settings.H_Max;
	IAPU.NextAPUTimerPos -= (Settings.H_Max * 10000L);
	if (IAPU.APUExecuting)
	{
	    APU.Cycles -= Settings.H_Max;
#ifdef MK_APU
		S9xCatchupCount();
#endif
	}
	else
	    APU.Cycles = 0;

	CPU.NextEvent = -1;
	ICPU.Scanline++;

	if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER))
	{
		CPU.V_Counter = 0;
		Memory.FillRAM[0x213F]^=0x80;
		PPU.RangeTimeOver = 0;
	    CPU.NMIActive = FALSE;
	    ICPU.Frame++;
	    PPU.HVBeamCounterLatched = 0;
	    CPU.Flags |= SCAN_KEYS_FLAG;
	    S9xStartHDMA ();
	}

	if (PPU.VTimerEnabled && !PPU.HTimerEnabled &&
	    CPU.V_Counter == PPU.IRQVBeamPos)
	{
	    S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE);
	}

	if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
	{
	    // Start of V-blank
	    S9xEndScreenRefresh ();
	    IPPU.HDMA = 0;
	    // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
#ifndef OPTI
	    missing.dma_this_frame = 0;
#endif // OPTI
	    IPPU.MaxBrightness = PPU.Brightness;
	    PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1;

		if(!PPU.ForcedBlanking){
			PPU.OAMAddr = PPU.SavedOAMAddr;
			{
				uint8 tmp = 0;
				if(PPU.OAMPriorityRotation)
					tmp = (PPU.OAMAddr&0xFE)>>1;
				if((PPU.OAMFlip&1) || PPU.FirstSprite!=tmp){
					PPU.FirstSprite=tmp;
					IPPU.OBJChanged=TRUE;
				}
			}
			PPU.OAMFlip = 0;
		}

	    Memory.FillRAM[0x4210] = 0x80 |Model->_5A22;
	    if (Memory.FillRAM[0x4200] & 0x80)
	    {
			CPU.NMIActive = TRUE;
			CPU.Flags |= NMI_FLAG;
			CPU.NMICycleCount = CPU.NMITriggerPoint;
	    }

#ifdef OLD_SNAPSHOT_CODE
	    if (CPU.Flags & SAVE_SNAPSHOT_FLAG)
		{
			CPU.Flags &= ~SAVE_SNAPSHOT_FLAG;
			Registers.PC = CPU.PC - CPU.PCBase;
			S9xPackStatus ();
			S9xAPUPackStatus ();
			Snapshot (NULL);
		}
#endif
	}
コード例 #3
0
void S9xDoHBlankProcessing()
{
#ifdef CPU_SHUTDOWN
   CPU.WaitCounter++;
#endif

   switch (CPU.WhichEvent)
   {
   case HBLANK_START_EVENT:
      if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
         IPPU.HDMA = S9xDoHDMA(IPPU.HDMA);
      break;

   case HBLANK_END_EVENT:
      asm_APU_EXECUTE(3); // notaz: run spc700 in sound 'speed hack' mode
      if (Settings.SuperFX)
         S9xSuperFXExec();

      CPU.Cycles -= Settings.H_Max;
      if (/*IAPU.APUExecuting*/CPU.APU_APUExecuting)
         CPU.APU_Cycles -= Settings.H_Max;
      else
         CPU.APU_Cycles = 0;

      CPU.NextEvent = -1;
      ICPU.Scanline++;

      if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER))
      {
         CPU.V_Counter = 0;
         CPU.NMIActive = FALSE;
         ICPU.Frame++;
         PPU.HVBeamCounterLatched = 0;
         CPU.Flags |= SCAN_KEYS_FLAG;
         S9xStartHDMA();
      }

      if (PPU.VTimerEnabled && !PPU.HTimerEnabled &&
            CPU.V_Counter == PPU.IRQVBeamPos)
         S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE);

      if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
      {
         // Start of V-blank
         S9xEndScreenRefresh();
         IPPU.HDMA = 0;
         // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
         missing.dma_this_frame = 0;
         IPPU.MaxBrightness = PPU.Brightness;
         PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1;

         if (!PPU.ForcedBlanking)
         {
            PPU.OAMAddr = PPU.SavedOAMAddr;
            PPU.OAMFlip = 0;
            PPU.FirstSprite = 0;
            if (PPU.OAMPriorityRotation)
               PPU.FirstSprite = PPU.OAMAddr >> 1;
         }

         Memory.FillRAM[0x4210] = 0x80;
         if (Memory.FillRAM[0x4200] & 0x80)
         {
            CPU.NMIActive = TRUE;
            CPU.Flags |= NMI_FLAG;
            CPU.NMICycleCount = CPU.NMITriggerPoint;
         }

      }
コード例 #4
0
ファイル: cpuexec.cpp プロジェクト: Tchaly/snes9x-rpi
void S9xDoHBlankProcessing (struct SCPUState *cpu, struct SAPU *apu, struct SIAPU *iapu)
{
	struct SPPU *ppu = &PPU;
	struct InternalPPU *ippu = &IPPU;

#ifdef CPU_SHUTDOWN
    cpu->WaitCounter++;
#endif
    switch (cpu->WhichEvent)
    {
    case HBLANK_START_EVENT:
		if (ippu->HDMA && cpu->V_Counter <= ppu->ScreenHeight)
			ippu->HDMA = S9xDoHDMA (ippu, ppu, cpu);
	break;

    case HBLANK_END_EVENT:
#ifndef _ZAURUS
	S9xSuperFXExec ();
#endif
#ifndef STORM
#endif

	cpu->Cycles -= Settings.H_Max;
	if (iapu->APUExecuting)
	    apu->Cycles -= Settings.H_Max;
	else
	    apu->Cycles = 0;

	cpu->NextEvent = -1;
	ICPU.Scanline++;

	if (++cpu->V_Counter > (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER))
	{
	    ppu->OAMAddr = ppu->SavedOAMAddr;
	    ppu->OAMFlip = 0;
	    cpu->V_Counter = 0;
	    cpu->NMIActive = FALSE;
	    ICPU.Frame++;
	    ppu->HVBeamCounterLatched = 0;
	    cpu->Flags |= SCAN_KEYS_FLAG;
	    S9xStartHDMA ();
	}

	if (ppu->VTimerEnabled && !ppu->HTimerEnabled &&
	    cpu->V_Counter == ppu->IRQVBeamPos)
	{
	    S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE, cpu);
	}

	if (cpu->V_Counter == ppu->ScreenHeight + FIRST_VISIBLE_LINE)
	{
	    // Start of V-blank
	    S9xEndScreenRefresh (ppu);
	    ppu->FirstSprite = 0;
	    ippu->HDMA = 0;
	    // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
	    missing.dma_this_frame = 0;
	    ippu->MaxBrightness = ppu->Brightness;
	    ppu->ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1;

	    Memory.FillRAM[0x4210] = 0x80;
	    if (Memory.FillRAM[0x4200] & 0x80)
	    {
			cpu->NMIActive = TRUE;
			cpu->Flags |= NMI_FLAG;
			cpu->NMICycleCount = cpu->NMITriggerPoint;
	    }

#ifdef OLD_SNAPSHOT_CODE
	    if (cpu->Flags & SAVE_SNAPSHOT_FLAG)
	    {
			cpu->Flags &= ~SAVE_SNAPSHOT_FLAG;
			Registers.PC = cpu->PC - cpu->PCBase;
			S9xPackStatus ();
			S9xAPUPackStatus ();
			Snapshot (NULL);
	    }
#endif
        }

	if (cpu->V_Counter == ppu->ScreenHeight + 3)
	    S9xUpdateJoypads (&IPPU);

	if (cpu->V_Counter == FIRST_VISIBLE_LINE)
	{
	    Memory.FillRAM[0x4210] = 0;
	    cpu->Flags &= ~NMI_FLAG;
	    S9xStartScreenRefresh ();
	}
	if (cpu->V_Counter >= FIRST_VISIBLE_LINE &&
	    cpu->V_Counter < ppu->ScreenHeight + FIRST_VISIBLE_LINE)
	{
	    RenderLine (cpu->V_Counter - FIRST_VISIBLE_LINE, ppu);
	}
	// Use TimerErrorCounter to skip update of SPC700 timers once
	// every 128 updates. Needed because this section of code is called
	// once every emulated 63.5 microseconds, which coresponds to
	// 15.750KHz, but the SPC700 timers need to be updated at multiples
	// of 8KHz, hence the error correction.
//	IAPU.TimerErrorCounter++;
//	if (IAPU.TimerErrorCounter >= )
//	    IAPU.TimerErrorCounter = 0;
//	else
	{
	    if (apu->TimerEnabled [2])
	    {
			apu->Timer [2] += 4;
			while (apu->Timer [2] >= apu->TimerTarget [2])
			{
				iapu->RAM [0xff] = (iapu->RAM [0xff] + 1) & 0xf;
				apu->Timer [2] -= apu->TimerTarget [2];
#ifdef SPC700_SHUTDOWN		
				iapu->WaitCounter++;
				iapu->APUExecuting = TRUE;
#endif		
			}
	    }
	    if (cpu->V_Counter & 1)
	    {
			if (apu->TimerEnabled [0])
			{
				apu->Timer [0]++;
				if (apu->Timer [0] >= apu->TimerTarget [0])
				{
					iapu->RAM [0xfd] = (iapu->RAM [0xfd] + 1) & 0xf;
					apu->Timer [0] = 0;
#ifdef SPC700_SHUTDOWN		
					iapu->WaitCounter++;
					iapu->APUExecuting = TRUE;
#endif		    
			    }
			}
			if (apu->TimerEnabled [1])
			{
				apu->Timer [1]++;
				if (apu->Timer [1] >= apu->TimerTarget [1])
				{
					iapu->RAM [0xfe] = (iapu->RAM [0xfe] + 1) & 0xf;
					apu->Timer [1] = 0;
#ifdef SPC700_SHUTDOWN		
					iapu->WaitCounter++;
					iapu->APUExecuting = TRUE;
#endif		    
			    }
			}
	    }
	}
	break; //HBLANK_END_EVENT

    case HTIMER_BEFORE_EVENT:
    case HTIMER_AFTER_EVENT:
	if (ppu->HTimerEnabled &&
	    (!ppu->VTimerEnabled || cpu->V_Counter == ppu->IRQVBeamPos))
	{
	    S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE, cpu);
	}
	break;
    }
コード例 #5
0
ファイル: cpuexec.cpp プロジェクト: BASLQC/snes9xTYL
void
S9xDoHBlankProcessing ()
{
	START_PROFILE_FUNC (S9xDoHBlankProcessing);
	
#ifdef CPU_SHUTDOWN
  CPU.WaitCounter++;
#endif
  switch (CPU.WhichEvent)
    {
    case HBLANK_START_EVENT:
      if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
	IPPU.HDMA = S9xDoHDMA (IPPU.HDMA);

      break;

    case HBLANK_END_EVENT:
      S9xSuperFXExec ();


      CPU.Cycles -= Settings.H_Max;
      (IAPUuncached->NextAPUTimerPos) -= (Settings.H_Max * 10000L);
      if ( (IAPUuncached->APUExecuting))
	(APUuncached->Cycles) -= Settings.H_Max;
      else
	(APUuncached->Cycles) = 0;

      CPU.NextEvent = -1;
      ICPU.Scanline++;

      if (++CPU.V_Counter >
	  (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER))
	{
	  PPU.OAMAddr = PPU.SavedOAMAddr;
	  PPU.OAMFlip = 0;
	  CPU.V_Counter = 0;
	  CPU.NMIActive = FALSE;
	  ICPU.Frame++;
	  PPU.HVBeamCounterLatched = 0;
	  CPU.Flags |= SCAN_KEYS_FLAG;
	  S9xStartHDMA ();
	}

      if (PPU.VTimerEnabled && !PPU.HTimerEnabled &&
	  CPU.V_Counter == PPU.IRQVBeamPos)
	{
	  S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE);
	}

      if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
	{
	  // Start of V-blank
	  S9xEndScreenRefresh ();
	  PPU.FirstSprite = 0;
	  IPPU.HDMA = 0;
	  // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
	  missing.dma_this_frame = 0;
	  IPPU.MaxBrightness = PPU.Brightness;
	  PPU.ForcedBlanking = (FillRAM[0x2100] >> 7) & 1;

	  FillRAM[0x4210] = 0x80;
	  if (FillRAM[0x4200] & 0x80)
	    {
	      CPU.NMIActive = TRUE;
	      CPU.Flags |= NMI_FLAG;
	      CPU.NMICycleCount = CPU.NMITriggerPoint;
	    }


	}

      if (CPU.V_Counter == PPU.ScreenHeight + 3)
	S9xUpdateJoypads ();

      if (CPU.V_Counter == FIRST_VISIBLE_LINE)
	{
	  FillRAM[0x4210] = 0;
	  CPU.Flags &= ~NMI_FLAG;
	  S9xStartScreenRefresh ();
	}
      if (CPU.V_Counter >= FIRST_VISIBLE_LINE &&
	  CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE)
	{
	  RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE);
	}

      break;
    case HTIMER_BEFORE_EVENT:
    case HTIMER_AFTER_EVENT:
      if (PPU.HTimerEnabled &&
	  (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos))
	{
	  S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE);
	}
      break;
    }
コード例 #6
0
void S9xDoHBlankProcessing ()
{
#ifdef CPU_SHUTDOWN
    CPU.WaitCounter++;
#endif
    switch (CPU.WhichEvent)
    {
    case HBLANK_START_EVENT:
		if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
			IPPU.HDMA = S9xDoHDMA (IPPU.HDMA);
	break;

    case HBLANK_END_EVENT:
	S9xSuperFXExec ();

#ifndef STORM
	if (Settings.SoundSync)
	    S9xGenerateSound ();
#endif

	CPU.Cycles -= Settings.H_Max;
	if (IAPU.APUExecuting)
	    APU.Cycles -= Settings.H_Max;
	else
	    APU.Cycles = 0;

	CPU.NextEvent = -1;
	ICPU.Scanline++;

	if (++CPU.V_Counter > (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER))
	{
	    PPU.OAMAddr = PPU.SavedOAMAddr;
	    PPU.OAMFlip = 0;
	    CPU.V_Counter = 0;
	    CPU.NMIActive = FALSE;
	    ICPU.Frame++;
	    PPU.HVBeamCounterLatched = 0;
	    CPU.Flags |= SCAN_KEYS_FLAG;
	    S9xStartHDMA ();
	}

	if (PPU.VTimerEnabled && !PPU.HTimerEnabled &&
	    CPU.V_Counter == PPU.IRQVBeamPos)
	{
	    S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE);
	}

	if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
	{
	    // Start of V-blank
	    S9xEndScreenRefresh ();
	    PPU.FirstSprite = 0;
	    IPPU.HDMA = 0;
	    // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
	    missing.dma_this_frame = 0;
	    IPPU.MaxBrightness = PPU.Brightness;
	    PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1;

	    Memory.FillRAM[0x4210] = 0x80;
	    if (Memory.FillRAM[0x4200] & 0x80)
	    {
			CPU.NMIActive = TRUE;
			CPU.Flags |= NMI_FLAG;
			CPU.NMICycleCount = CPU.NMITriggerPoint;
	    }

#ifdef OLD_SNAPSHOT_CODE
	    if (CPU.Flags & SAVE_SNAPSHOT_FLAG)
	    {
			CPU.Flags &= ~SAVE_SNAPSHOT_FLAG;
			Registers.PC = CPU.PC - CPU.PCBase;
			S9xPackStatus ();
			S9xAPUPackStatus ();
			Snapshot (NULL);
	    }
#endif
        }

	if (CPU.V_Counter == PPU.ScreenHeight + 3)
	    S9xUpdateJoypads ();

	if (CPU.V_Counter == FIRST_VISIBLE_LINE)
	{
	    Memory.FillRAM[0x4210] = 0;
	    CPU.Flags &= ~NMI_FLAG;
	    S9xStartScreenRefresh ();
	}
	if (CPU.V_Counter >= FIRST_VISIBLE_LINE &&
	    CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE)
	{
	    RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE);
	}
	// Use TimerErrorCounter to skip update of SPC700 timers once
	// every 128 updates. Needed because this section of code is called
	// once every emulated 63.5 microseconds, which coresponds to
	// 15.750KHz, but the SPC700 timers need to be updated at multiples
	// of 8KHz, hence the error correction.
//	IAPU.TimerErrorCounter++;
//	if (IAPU.TimerErrorCounter >= )
//	    IAPU.TimerErrorCounter = 0;
//	else
	{
	    if (APU.TimerEnabled [2])
	    {
			APU.Timer [2] += 4;
			while (APU.Timer [2] >= APU.TimerTarget [2])
			{
				IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf;
				APU.Timer [2] -= APU.TimerTarget [2];
#ifdef SPC700_SHUTDOWN		
				IAPU.WaitCounter++;
				IAPU.APUExecuting = TRUE;
#endif		
			}
	    }
	    if (CPU.V_Counter & 1)
	    {
			if (APU.TimerEnabled [0])
			{
				APU.Timer [0]++;
				if (APU.Timer [0] >= APU.TimerTarget [0])
				{
					IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf;
					APU.Timer [0] = 0;
#ifdef SPC700_SHUTDOWN		
					IAPU.WaitCounter++;
					IAPU.APUExecuting = TRUE;
#endif		    
			    }
			}
			if (APU.TimerEnabled [1])
			{
				APU.Timer [1]++;
				if (APU.Timer [1] >= APU.TimerTarget [1])
				{
					IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf;
					APU.Timer [1] = 0;
#ifdef SPC700_SHUTDOWN		
					IAPU.WaitCounter++;
					IAPU.APUExecuting = TRUE;
#endif		    
			    }
			}
	    }
	}
	break; //HBLANK_END_EVENT

    case HTIMER_BEFORE_EVENT:
    case HTIMER_AFTER_EVENT:
	if (PPU.HTimerEnabled &&
	    (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos))
	{
	    S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE);
	}
	break;
    }