示例#1
0
void Apu0D()
{
   // PUSH PSW
   S9xAPUPackStatus();
   Push(IAPU.Registers.P);
   IAPU.PC++;
}
示例#2
0
void Apu0F()
{
   // BRK

   SPC700_PushW(IAPU.PC + 1 - IAPU.RAM);
   S9xAPUPackStatus();
   Push(IAPU.Registers.P);
   APUSetBreak();
   APUClearInterrupt();
   // XXX:Where is the BRK vector ???
   IAPU.PC = IAPU.RAM + APU.ExtraRAM[0x20] + (APU.ExtraRAM[0x21] << 8);
}
示例#3
0
static void SPCPlayExec(void)
{
	for (int v = 0; v < Timings.V_Max; v++)
	{
		S9xAPUExecute();
		APU.Cycles -= (Timings.H_Max << SNES_APU_ACCURACY);
		IAPU.NextAPUTimerPos -= (Timings.H_Max << SNES_APU_ACCURACY);
	}

	APURegisters.PC = IAPU.PC - IAPU.RAM;
    S9xAPUPackStatus();
}
示例#4
0
void
S9xMainLoop(void)
{
#ifndef ASMCPU
   if (Settings.APUEnabled == 1)
   {
#ifdef USE_SA1
      if (Settings.SA1)
         S9xMainLoop_SA1_APU();
      else
#endif
         S9xMainLoop_NoSA1_APU();
   }
   else
   {
#ifdef USE_SA1
      if (Settings.SA1)
         S9xMainLoop_SA1_NoAPU();
      else
#endif
         S9xMainLoop_NoSA1_NoAPU();
   }
#else
#ifdef ASM_SPC700
   if (Settings.asmspc700)
      asmMainLoop_spcAsm(&CPU);
   else
#endif
      asmMainLoop_spcC(&CPU);
#endif
   Registers.PC = CPU.PC - CPU.PCBase;

#ifndef ASMCPU
   S9xPackStatus();
#endif

   S9xAPUPackStatus();


   //if (CPU.Flags & SCAN_KEYS_FLAG)
   // {
   CPU.Flags &= ~SCAN_KEYS_FLAG;
   //}

   if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2)
   {
      CPU.TriedInterleavedMode2 = TRUE;
      CPU.BRKTriggered = FALSE;
      S9xDeinterleaveMode2();
   }
}
void Apu0F()
{
   // BRK

#if 0
   STOP("BRK");
#else
   PushW((IAPU.PC + 1 - IAPU.RAM));
   S9xAPUPackStatus();
   Push(IAPU.P);
   APUSetBreak();
   APUClearInterrupt();
   // XXX:Where is the BRK vector ???
   IAPU.PC = IAPU.RAM + APU.ExtraRAM[0x20] + (APU.ExtraRAM[0x21] << 8);
#endif
}
示例#6
0
/* get samples
   ---------------------------------------------------------------- */
void SPC_update(unsigned char *buf)
{
    // APU_LOOP
    int c, ic;

#if 1
    for (c = 0; c < 2048000 / 32 / RATE; c ++) {
        for (ic = 0; ic < 32; ic ++)
            APU_EXECUTE1(); IAPU.TimerErrorCounter ++; DoTimer();
    }
#else
    for (APU.Cycles = 0; APU.Cycles < 204800 / RATE; APU.Cycles ++) {
        APU_EXECUTE1();
        ++ IAPU.TimerErrorCounter;
        if ((IAPU.TimerErrorCounter & 31) == 0)
            DoTimer();
        APURegisters.PC = IAPU.PC - IAPU.RAM;
        S9xAPUPackStatus();
    }
#endif

    S9xMixSamples ((unsigned char *)buf, samples_per_mix);
}
示例#7
0
void S9xMainLoop (void)
{
	for (;;)
	{
		APU_EXECUTE();
		
		if (CPU.Flags)
		{
			if (CPU.Flags & NMI_FLAG)
			{
				if (Timings.NMITriggerPos <= CPU.Cycles)
				{
					CPU.Flags &= ~NMI_FLAG;
					Timings.NMITriggerPos = 0xffff;
					if (CPU.WaitingForInterrupt)
					{
						CPU.WaitingForInterrupt = FALSE;
						Registers.PCw++;
					}
				
					S9xOpcode_NMI();
				}
			}
		
#ifdef DEBUGGER
			if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG))
			{
				for (int Break = 0; Break != 6; Break++)
				{
					if (S9xBreakpoint[Break].Enabled &&
						S9xBreakpoint[Break].Bank == Registers.PB &&
						S9xBreakpoint[Break].Address == Registers.PCw)
					{
						if (S9xBreakpoint[Break].Enabled == 2)
							S9xBreakpoint[Break].Enabled = TRUE;
						else
							CPU.Flags |= DEBUG_MODE_FLAG;
					}
				}
			}
#endif
			
			CHECK_SOUND();

			if (CPU.Flags & IRQ_PENDING_FLAG)
			{
				if (CPU.WaitingForInterrupt)
				{
					CPU.WaitingForInterrupt = FALSE;
					Registers.PCw++;
				}

				if (CPU.IRQActive && !Settings.DisableIRQ)
				{
					if (!CheckFlag(IRQ))
						S9xOpcode_IRQ();
				}
				else
					CPU.Flags &= ~IRQ_PENDING_FLAG;
			}
			
			if (CPU.Flags & SCAN_KEYS_FLAG)
				break;

#ifdef DEBUGGER
			if (CPU.Flags & DEBUG_MODE_FLAG)
				break;

			if (CPU.Flags & TRACE_FLAG)
				S9xTrace();

			if (CPU.Flags & SINGLE_STEP_FLAG)
			{
				CPU.Flags &= ~SINGLE_STEP_FLAG;
				CPU.Flags |= DEBUG_MODE_FLAG;
			}
#endif
		}
		
#ifdef CPU_SHUTDOWN
		CPU.PBPCAtOpcodeStart = Registers.PBPC;
#endif

		register uint8				Op;
		register struct	SOpcodes	*Opcodes;
		
		if (CPU.PCBase)
		{
			Op = CPU.PCBase[Registers.PCw];
			CPU.Cycles += CPU.MemSpeed;
			Opcodes = ICPU.S9xOpcodes;
		}
		else
		{
			Op = S9xGetByte(Registers.PBPC);
			OpenBus = Op;
			Opcodes = S9xOpcodesSlow;
		}
		
		if ((Registers.PCw&MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
		{
			uint8	*oldPCBase = CPU.PCBase;

			CPU.PCBase = GetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4)));
			if (oldPCBase!=CPU.PCBase || (Registers.PCw&~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK))
				Opcodes = S9xOpcodesSlow;
		}
		
		Registers.PCw++;
		(*Opcodes[Op].S9xOpcode)();
				
		S9xUpdateAPUTimer();
		
		if (SA1.Executing)
			S9xSA1MainLoop();
		
		if (CPU.Cycles >= CPU.NextEvent)
			S9xDoHEventProcessing();
    }
	
    S9xPackStatus();
    APURegisters.PC = IAPU.PC - IAPU.RAM;
    S9xAPUPackStatus();
	
    if (CPU.Flags & SCAN_KEYS_FLAG)
    {
#ifdef DEBUGGER
		if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
#endif
		S9xSyncSpeed();
		CPU.Flags &= ~SCAN_KEYS_FLAG;
    }
}
示例#8
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;
	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
	}
示例#9
0
void S9xMainLoop (void)
{
    for (;;)
    {
#ifdef DEBUG_MAXCOUNT
      CPU.GlobalLoopCount++;
      if(Settings.MaxCount && CPU.GlobalLoopCount == Settings.MaxCount) {
        fprintf(stderr, "Max loop count reached: %ld \n", Settings.MaxCount);
        S9xExit();
      }
#endif

	APU_EXECUTE ();
	if (CPU.Flags)
	{
	    if (CPU.Flags & NMI_FLAG)
	    {
		if (--CPU.NMICycleCount == 0)
		{
		    CPU.Flags &= ~NMI_FLAG;
		    if (CPU.WaitingForInterrupt)
		    {
			CPU.WaitingForInterrupt = FALSE;
			CPU.PC++;
		    }
		    S9xOpcode_NMI ();
		}
	    }

#ifdef DEBUGGER
	    if ((CPU.Flags & BREAK_FLAG) &&
		!(CPU.Flags & SINGLE_STEP_FLAG))
	    {
		for (int Break = 0; Break != 6; Break++)
		{
		    if (S9xBreakpoint[Break].Enabled &&
			S9xBreakpoint[Break].Bank == Registers.PB &&
			S9xBreakpoint[Break].Address == CPU.PC - CPU.PCBase)
		    {
			if (S9xBreakpoint[Break].Enabled == 2)
			    S9xBreakpoint[Break].Enabled = TRUE;
			else
			    CPU.Flags |= DEBUG_MODE_FLAG;
		    }
		}
	    }
#endif
	    CHECK_SOUND ();

	    if (CPU.Flags & IRQ_PENDING_FLAG)
	    {
		if (CPU.IRQCycleCount == 0)
		{
		    if (CPU.WaitingForInterrupt)
		    {
			CPU.WaitingForInterrupt = FALSE;
			CPU.PC++;
		    }
		    if (CPU.IRQActive && !Settings.DisableIRQ)
		    {
			if (!CheckFlag (IRQ))
			    S9xOpcode_IRQ ();
		    }
		    else
			CPU.Flags &= ~IRQ_PENDING_FLAG;
		}
		else
                {
                    if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ))
                        CPU.IRQCycleCount=1;
                }
	    }
#ifdef DEBUGGER
	    if (CPU.Flags & DEBUG_MODE_FLAG)
		break;
#endif
	    if (CPU.Flags & SCAN_KEYS_FLAG)
		break;
#ifdef DEBUGGER
	    if (CPU.Flags & TRACE_FLAG)
		S9xTrace ();

	    if (CPU.Flags & SINGLE_STEP_FLAG)
	    {
		CPU.Flags &= ~SINGLE_STEP_FLAG;
		CPU.Flags |= DEBUG_MODE_FLAG;
	    }
#endif
	}
#ifdef CPU_SHUTDOWN
	CPU.PCAtOpcodeStart = CPU.PC;
#endif
	CPU.Cycles += CPU.MemSpeed;

	(*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) ();
	
	S9xUpdateAPUTimer();
	
	if (SA1.Executing)
	    S9xSA1MainLoop ();
	DO_HBLANK_CHECK();
    }
    Registers.PC = CPU.PC - CPU.PCBase;
    S9xPackStatus ();
    APURegisters.PC = IAPU.PC - IAPU.RAM;
    S9xAPUPackStatus ();
    if (CPU.Flags & SCAN_KEYS_FLAG)
    {
#ifdef DEBUGGER
	if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
#endif
	    S9xSyncSpeed ();
	CPU.Flags &= ~SCAN_KEYS_FLAG;
    }
#ifdef DETECT_NASTY_FX_INTERLEAVE
    if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2)
    {
	CPU.TriedInterleavedMode2 = TRUE;
	CPU.BRKTriggered = FALSE;
	S9xDeinterleaveMode2 ();
    }
#endif
}
示例#10
0
void S9xMainLoop (void)
{
	if(ICPU.SavedAtOp)
	{
		ICPU.SavedAtOp = FALSE;
		Registers.PCw = CPU.PBPCAtOpcodeStart;
		if(CPU.PCBase)
			CPU.Cycles -= CPU.MemSpeed;
		goto doOp;
	}

	for (;;)
	{
		if (CPU.Flags)
		{
			if (CPU.Flags & NMI_FLAG)
			{
				if (Timings.NMITriggerPos <= CPU.Cycles)
				{
					CPU.Flags &= ~NMI_FLAG;
					Timings.NMITriggerPos = 0xffff;
					if (CPU.WaitingForInterrupt)
					{
						CPU.WaitingForInterrupt = FALSE;
						Registers.PCw++;
					}

					S9xOpcode_NMI();
				}
			}

#ifdef DEBUGGER
			if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG))
			{
				for (int Break = 0; Break != 6; Break++)
				{
					if (S9xBreakpoint[Break].Enabled &&
						S9xBreakpoint[Break].Bank == Registers.PB &&
						S9xBreakpoint[Break].Address == Registers.PCw)
					{
						if (S9xBreakpoint[Break].Enabled == 2)
							S9xBreakpoint[Break].Enabled = TRUE;
						else
							CPU.Flags |= DEBUG_MODE_FLAG;
					}
				}
			}
#endif

			CHECK_SOUND();

			if (CPU.Flags & IRQ_FLAG)
			{
				if (CPU.IRQPending)
					// FIXME: In case of IRQ during WRAM refresh
					CPU.IRQPending = 0;
				else
				{
					if (CPU.WaitingForInterrupt)
					{
						CPU.WaitingForInterrupt = FALSE;
						Registers.PCw++;
					}

					if (CPU.IRQActive && !Settings.DisableIRQ)
					{
						if (!CheckFlag(IRQ))
						// in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared.
							S9xOpcode_IRQ();
					}
					else
						CPU.Flags &= ~IRQ_FLAG;
				}
			}

			if (CPU.Flags & SCAN_KEYS_FLAG)
				break;

#ifdef DEBUGGER
			if (CPU.Flags & DEBUG_MODE_FLAG)
				break;

			if (CPU.Flags & TRACE_FLAG)
				S9xTrace();

			if (CPU.Flags & SINGLE_STEP_FLAG)
			{
				CPU.Flags &= ~SINGLE_STEP_FLAG;
				CPU.Flags |= DEBUG_MODE_FLAG;
			}
#endif
		}

#ifdef CPU_SHUTDOWN
		CPU.PBPCAtOpcodeStart = Registers.PBPC;
#endif
	doOp:
		register uint8				Op;
		register struct	SOpcodes	*Opcodes;

		CPU.PrevCycles = CPU.Cycles;

		if (CPU.PCBase)
		{
			Op = CPU.PCBase[Registers.PCw];
			CPU.Cycles += CPU.MemSpeed;
			Opcodes = ICPU.S9xOpcodes;
		}
		else
		{
			Op = S9xGetByte(Registers.PBPC);
			OpenBus = Op;
			Opcodes = S9xOpcodesSlow;
		}

		if ((Registers.PCw&MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
		{
			uint8	*oldPCBase = CPU.PCBase;

			CPU.PCBase = GetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4)));
			if (oldPCBase!=CPU.PCBase || (Registers.PCw&~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK))
				Opcodes = S9xOpcodesSlow;
		}

		Registers.PCw++;
		(*Opcodes[Op].S9xOpcode)();

		if(ICPU.SavedAtOp)
		{
			ICPU.SavedAtOp = false;
			continue;
		}

		S9xAPUExecute();

		if (SA1.Executing)
			S9xSA1MainLoop();

		while (CPU.Cycles >= CPU.NextEvent)
			S9xDoHEventProcessing();
    }

    S9xPackStatus();
    APURegisters.PC = IAPU.PC - IAPU.RAM;
    S9xAPUPackStatus();

    if (CPU.Flags & SCAN_KEYS_FLAG)
    {
#ifdef DEBUGGER
		if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
#endif
		S9xSyncSpeed();
		CPU.Flags &= ~SCAN_KEYS_FLAG;
    }
}
示例#11
0
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;
    }
示例#12
0
void
S9xMainLoop (void)
{
  for (;;)
    {
      APU_EXECUTE ();
      if (CPU.Flags)
	{
	  if (CPU.Flags & NMI_FLAG)
	    {
	      if (--CPU.NMICycleCount == 0)
		{
		  CPU.Flags &= ~NMI_FLAG;
		  if (CPU.WaitingForInterrupt)
		    {
		      CPU.WaitingForInterrupt = FALSE;
		      CPU.PC++;
		    }
		  S9xOpcode_NMI ();
		}
	    }

	  if (CPU.Flags & IRQ_PENDING_FLAG)
	    {
	      if (CPU.IRQCycleCount == 0)
		{
		  if (CPU.WaitingForInterrupt)
		    {
		      CPU.WaitingForInterrupt = FALSE;
		      CPU.PC++;
		    }
		  if (CPU.IRQActive && !Settings.DisableIRQ)
		    {
		      if (!CheckFlag (IRQ))
			S9xOpcode_IRQ ();
		    }
		  else
		    CPU.Flags &= ~IRQ_PENDING_FLAG;
		}
	      else
		CPU.IRQCycleCount--;
	    }
	  if (CPU.Flags & SCAN_KEYS_FLAG)
	    break;
	}

#ifdef CPU_SHUTDOWN
      CPU.PCAtOpcodeStart = CPU.PC;
#endif
      CPU.Cycles += CPU.MemSpeed;

      (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) ();


      S9xUpdateAPUTimer ();


      if (SA1.Executing)
	S9xSA1MainLoop ();
      DO_HBLANK_CHECK ();

    }


  Registers.PC = CPU.PC - CPU.PCBase;
  S9xPackStatus ();
  (APURegistersUncached->PC) = (IAPUuncached->PC) - (IAPUuncached->RAM);
  S9xAPUPackStatus ();

  if (CPU.Flags & SCAN_KEYS_FLAG)
    {
      S9xSyncSpeed ();
      CPU.Flags &= ~SCAN_KEYS_FLAG;
    }

  if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2)
    {
      CPU.TriedInterleavedMode2 = TRUE;
      CPU.BRKTriggered = FALSE;
      S9xDeinterleaveMode2 ();
    }

}
示例#13
0
void S9xMainLoop (struct SRegisters * reg, struct SICPU * icpu, struct SCPUState * cpu)
{
#else
void S9xMainLoop (void)
{
	struct SICPU		* icpu  = &ICPU;
	struct SCPUState	* cpu	= &CPU;
	struct SRegisters	* reg	= &Registers;
#endif
    for (;;)
    {
		APU_EXECUTE ();

		if (CPU.Flags)
		{
			if (CPU.Flags & NMI_FLAG)
			{
				if (--CPU.NMICycleCount == 0)
				{
					CPU.Flags &= ~NMI_FLAG;
					if (CPU.WaitingForInterrupt)
					{
						CPU.WaitingForInterrupt = FALSE;
						++CPU.PC;
					}
					S9xOpcode_NMI ();
				}
			}

#ifdef DEBUGGER
			if ((CPU.Flags & BREAK_FLAG) &&
			!(CPU.Flags & SINGLE_STEP_FLAG))
			{
				for (int Break = 0; Break != 6; Break++)
				{
					if (S9xBreakpoint[Break].Enabled &&
					S9xBreakpoint[Break].Bank == Registers.PB &&
					S9xBreakpoint[Break].Address == CPU.PC - CPU.PCBase)
					{
						if (S9xBreakpoint[Break].Enabled == 2)
							S9xBreakpoint[Break].Enabled = TRUE;
						else
							CPU.Flags |= DEBUG_MODE_FLAG;
					}
				}
			}
#endif
			CHECK_SOUND ();

			if (CPU.Flags & IRQ_PENDING_FLAG)
			{
				if (CPU.IRQCycleCount == 0)
				{
					if (CPU.WaitingForInterrupt)
					{
						CPU.WaitingForInterrupt = FALSE;
						CPU.PC++;
					}
					if (CPU.IRQActive && !Settings.DisableIRQ)
					{
						if (!CHECKFLAG (IRQ))
							S9xOpcode_IRQ ();
					}
					else
						CPU.Flags &= ~IRQ_PENDING_FLAG;
				}
				else
					CPU.IRQCycleCount--;
			}
#ifdef DEBUGGER
			if (CPU.Flags & DEBUG_MODE_FLAG)
				break;
#endif
			if (CPU.Flags & SCAN_KEYS_FLAG)
				break;
#ifdef DEBUGGER
			if (CPU.Flags & TRACE_FLAG)
				S9xTrace ();

			if (CPU.Flags & SINGLE_STEP_FLAG)
			{
				CPU.Flags &= ~SINGLE_STEP_FLAG;
				CPU.Flags |= DEBUG_MODE_FLAG;
			}
#endif
		} //if (CPU.Flags)
#ifdef CPU_SHUTDOWN
		CPU.PCAtOpcodeStart = CPU.PC;
#endif
#ifdef VAR_CYCLES
		CPU.Cycles += CPU.MemSpeed;
#else
		CPU.Cycles += ICPU.Speed [*CPU.PC];
#endif
		(*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (&Registers, &ICPU, &CPU);
	
		if (SA1.Executing)
			S9xSA1MainLoop ();
		DO_HBLANK_CHECK();
	} // for(;;)
    Registers.PC = CPU.PC - CPU.PCBase;
    S9xPackStatus ();
    APURegisters.PC = IAPU.PC - IAPU.RAM;
    S9xAPUPackStatus ();
    if (CPU.Flags & SCAN_KEYS_FLAG)
    {
#ifdef DEBUGGER
		if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
#endif
			S9xSyncSpeed ();
		CPU.Flags &= ~SCAN_KEYS_FLAG;
    }
    if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2)
    {
		CPU.TriedInterleavedMode2 = TRUE;
		CPU.BRKTriggered = FALSE;
		S9xDeinterleaveMode2 ();
    }
}


void S9xSetIRQ (uint32 source)
{
    CPU.IRQActive |= source;
    CPU.Flags |= IRQ_PENDING_FLAG;
    CPU.IRQCycleCount = 3;
    if (CPU.WaitingForInterrupt)
    {
		// Force IRQ to trigger immediately after WAI - 
		// Final Fantasy Mystic Quest crashes without this.
		CPU.IRQCycleCount = 0;
		CPU.WaitingForInterrupt = FALSE;
		CPU.PC++;
    }
}
示例#14
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;
    }