예제 #1
0
void S9xMainLoop_SA1_APU (void) {
	for (;;) { 
		UPDATE_APU_COUNTER();
		
    if (CPUPack.CPU.Flags) {
	  	if (CPUPack.CPU.Flags & NMI_FLAG) {
	      if (--CPUPack.CPU.NMICycleCount == 0) {
		  		CPUPack.CPU.Flags &= ~NMI_FLAG;
		  		if (CPUPack.CPU.WaitingForInterrupt) {
		      	CPUPack.CPU.WaitingForInterrupt = FALSE;
		      	CPUPack.CPU.PC++;
		    	}
		  		S9xOpcode_NMI ();
				}
	    }

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

		#ifdef CPU_SHUTDOWN
    CPUPack.CPU.PCAtOpcodeStart = CPUPack.CPU.PC;
		#endif
				
    CPUPack.CPU.Cycles += CPUPack.CPU.MemSpeed;
	extern int  os9x_SA1_exec;
	for(int i=0;i<os9x_SA1_exec;i++)
		(*CPUPack.ICPU.S9xOpcodes[*CPUPack.CPU.PC++].S9xOpcode) ();

    //S9xUpdateAPUTimer ();

    if (SA1Pack_SA1.Executing) S9xSA1MainLoop ();
      
    DO_HBLANK_CHECK ();
  }
}
예제 #2
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
}
예제 #3
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;
    }
}
예제 #4
0
void S9xMainLoop_SA1_APU(void)
{
   for (;;)
   {
      asm_APU_EXECUTE(1);
      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
#ifdef VAR_CYCLES
      CPU.Cycles += CPU.MemSpeed;
#else
      CPU.Cycles += ICPU.Speed [*CPU.PC];
#endif
      (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode)();


      //S9xUpdateAPUTimer ();


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

   }
}
예제 #5
0
void S9xMainLoop(void)
{
	int i;
	
	for (;;)
	{
		for (i=0;i<32;i++) render_snescast();
		if (CPU.NMILine)
		{
			if (Timings.NMITriggerPos <= CPU.Cycles)
			{
				CPU.NMILine = FALSE;
				Timings.NMITriggerPos = 0xffff;
				if (CPU.WaitingForInterrupt)
				{
					CPU.WaitingForInterrupt = FALSE;
					Registers.PCw++;
				}

				S9xOpcode_NMI();
			}
		}

		if (CPU.IRQTransition || CPU.IRQExternal)
		{
			if (CPU.IRQPending)
				CPU.IRQPending--;
			else
			{
				if (CPU.WaitingForInterrupt)
				{
					CPU.WaitingForInterrupt = FALSE;
					Registers.PCw++;
				}

				CPU.IRQTransition = FALSE;
				CPU.IRQPending = Timings.IRQPendCount;

				if (!CheckFlag(IRQ))
					S9xOpcode_IRQ();
			}
		}

	#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;
				}
			}
		}

		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

		if (CPU.Flags & SCAN_KEYS_FLAG)
			break;

		register uint8				Op;
		register struct	SOpcodes	*Opcodes;

		if (CPU.PCBase)
		{
			Op = CPU.PCBase[Registers.PCw];
			CPU.PrevCycles = CPU.Cycles;
			CPU.Cycles += CPU.MemSpeed;
			S9xCheckInterrupts();
			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 = S9xGetBasePointer(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 (Settings.SA1)
			S9xSA1MainLoop();
	}

	S9xPackStatus();

	if (CPU.Flags & SCAN_KEYS_FLAG)
	{
	#ifdef DEBUGGER
		if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
	#endif
		S9xSyncSpeed();
		CPU.Flags &= ~SCAN_KEYS_FLAG;
	}
}
예제 #6
0
파일: cpuexec.cpp 프로젝트: dborth/snes9xgx
void S9xMainLoop (void)
{
	#define CHECK_FOR_IRQ_CHANGE() \
	if (Timings.IRQFlagChanging) \
	{ \
		if (Timings.IRQFlagChanging & IRQ_TRIGGER_NMI) \
		{ \
			CPU.NMIPending = TRUE; \
			Timings.NMITriggerPos = CPU.Cycles + 6; \
		} \
		if (Timings.IRQFlagChanging & IRQ_CLEAR_FLAG) \
			ClearIRQ(); \
		else if (Timings.IRQFlagChanging & IRQ_SET_FLAG) \
			SetIRQ(); \
		Timings.IRQFlagChanging = IRQ_NONE; \
	}

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

	for (;;)
	{
		if (CPU.NMIPending)
		{
			#ifdef DEBUGGER
			if (Settings.TraceHCEvent)
			    S9xTraceFormattedMessage ("Comparing %d to %d\n", Timings.NMITriggerPos, CPU.Cycles);
			#endif
			if (Timings.NMITriggerPos <= CPU.Cycles)
			{
				CPU.NMIPending = FALSE;
				Timings.NMITriggerPos = 0xffff;
				if (CPU.WaitingForInterrupt)
				{
					CPU.WaitingForInterrupt = FALSE;
					Registers.PCw++;
					CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2;
					while (CPU.Cycles >= CPU.NextEvent)
						S9xDoHEventProcessing();
				}

				CHECK_FOR_IRQ_CHANGE();
				S9xOpcode_NMI();
			}
		}

		if (CPU.Cycles >= Timings.NextIRQTimer)
		{
			#ifdef DEBUGGER
			S9xTraceMessage ("Timer triggered\n");
			#endif

			S9xUpdateIRQPositions(false);
			CPU.IRQLine = TRUE;
		}

		if (CPU.IRQLine || CPU.IRQExternal)
		{
			if (CPU.WaitingForInterrupt)
			{
				CPU.WaitingForInterrupt = FALSE;
				Registers.PCw++;
				CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2;
				while (CPU.Cycles >= CPU.NextEvent)
					S9xDoHEventProcessing();
			}

			if (!CheckFlag(IRQ))
			{
				/* The flag pushed onto the stack is the new value */
				CHECK_FOR_IRQ_CHANGE();
				S9xOpcode_IRQ();
			}
		}

		/* Change IRQ flag for instructions that set it only on last cycle */
		CHECK_FOR_IRQ_CHANGE();

	#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;
				}
			}
		}

		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

		if (CPU.Flags & SCAN_KEYS_FLAG)
		{
			#ifdef DEBUGGER
			if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
			#endif
			{
				S9xSyncSpeed();
			}

			break;
		}

		uint8				Op;
		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 = S9xGetBasePointer(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 (Settings.SA1)
			S9xSA1MainLoop();
	}

	S9xPackStatus();
}
예제 #7
0
void S9xMainLoop (void)
{
	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

			if (CPU.Flags & IRQ_FLAG)
			{
				if (CPU.IRQPending)
					// FIXME: In case of IRQ during WRAM refresh
					CPU.IRQPending--;
				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

		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 = S9xGetBasePointer(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 (SA1.Executing)
			S9xSA1MainLoop();

	#if (S9X_ACCURACY_LEVEL <= 2)
		while (CPU.Cycles >= CPU.NextEvent)
			S9xDoHEventProcessing();
	#endif
	}

	S9xPackStatus();

	if (CPU.Flags & SCAN_KEYS_FLAG)
	{
	#ifdef DEBUGGER
		if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
	#endif
		S9xSyncSpeed();
		CPU.Flags &= ~SCAN_KEYS_FLAG;
	}
}
예제 #8
0
void S9xMainLoop (void)
{
    static int loop_times=0;
    int loops2=0;
    //printf("Enter S9xMainLoop %d %x\n", loop_times, Registers.PCw);
	for (;;)
	{
        loops2++;
        //printf("S9xMainLoop %d for loop %d flags=%d\n", loop_times, loops2, CPU.Flags);
		if (CPU.NMILine)
		{
            //printf("case 1\n");
			if (Timings.NMITriggerPos <= CPU.Cycles)
			{
				CPU.NMILine = FALSE;
				Timings.NMITriggerPos = 0xffff;
				if (CPU.WaitingForInterrupt)
				{
					CPU.WaitingForInterrupt = FALSE;
					Registers.PCw++;
				}

				S9xOpcode_NMI();
			}
		}

		if (CPU.IRQTransition || CPU.IRQExternal)
		{   
            //printf("case 2\n");
			if (CPU.IRQPending)
				CPU.IRQPending--;
			else
			{
				if (CPU.WaitingForInterrupt)
				{
					CPU.WaitingForInterrupt = FALSE;
					Registers.PCw++;
				}

				CPU.IRQTransition = FALSE;
				CPU.IRQPending = Timings.IRQPendCount;

				if (!CheckFlag(IRQ))
					S9xOpcode_IRQ();
			}
		}

	#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;
				}
			}
		}

		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

		if (CPU.Flags & SCAN_KEYS_FLAG)
			break;

		register uint8				Op;
		register Opcode				*Opcodes;

		if (CPU.PCBase)            
		{   
			Op = CPU.PCBase[Registers.PCw];
            
			CPU.PrevCycles = CPU.Cycles;
			CPU.Cycles += CPU.MemSpeed;            
			S9xCheckInterrupts();
			Opcodes = ICPU.S9xOpcodes;
            //printf("case 3 %x %x %d %d\n", Registers.PCw, Op, CPU.PrevCycles, CPU.Cycles);
		}
		else
		{
            //printf("case 4\n");
			Op = S9xGetByte(Registers.PBPC);
			OpenBus = Op;
			Opcodes = S9xOpcodesSlow;
		}

		if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
		{            
			uint8	*oldPCBase = CPU.PCBase;
            //printf("case 5\n");

			CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4)));
			if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK))
				Opcodes = S9xOpcodesSlow;
		}
        //printf("case 3.1 %d\n", CPU.Cycles);
		Registers.PCw++;
		Opcodes[Op]();
        //printf("case 3.2 %d\n", CPU.Cycles);

		if (Settings.SA1){
            //printf("case 6\n");
			S9xSA1MainLoop();
        }
	}

	S9xPackStatus();

	if (CPU.Flags & SCAN_KEYS_FLAG)
	{
        //printf("case 7\n");
	#ifdef DEBUGGER
		if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
	#endif
		S9xSyncSpeed();
		CPU.Flags &= ~SCAN_KEYS_FLAG;
	}
    //printf("Exit S9xMainLoop %d loops2=%d\n", loop_times++, loops2);
}
예제 #9
0
void S9xMainLoop (void)
{
	struct SCPUState *cpu = &CPU;
	struct SICPU *icpu = &ICPU;
	struct SIAPU *iapu = &IAPU;
	struct SAPU *apu = &APU;
	struct SRegisters *reg = &Registers;
	struct SAPURegisters *areg = &APURegisters;

    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)
//					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) (reg, icpu, cpu);
#ifndef _ZAURUS
		if (SA1.Executing)
			S9xSA1MainLoop ();
#endif
		DO_HBLANK_CHECK();
	} // for(;;)
    Registers.PC = cpu->PC - cpu->PCBase;
    S9xPackStatus ();
    areg->PC = iapu->PC - iapu->RAM;
    S9xAPUPackStatus_OP ();
    if (cpu->Flags & SCAN_KEYS_FLAG)
    {
#ifdef DEBUGGER
		if (!(cpu->Flags & FRAME_ADVANCE_FLAG))
#endif
			S9xSyncSpeed ();
		cpu->Flags &= ~SCAN_KEYS_FLAG;
    }
#ifndef _ZAURUS
    if (cpu->BRKTriggered && Settings.SuperFX && !cpu->TriedInterleavedMode2)
    {
		cpu->TriedInterleavedMode2 = TRUE;
		cpu->BRKTriggered = FALSE;
		S9xDeinterleaveMode2 ();
    }
#endif
}
예제 #10
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 ();
    }

}
예제 #11
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++;
    }
}
예제 #12
0
void S9xMainLoop (void)
{
	do
	{
		register uint8	Op;
		register struct	SOpcodes *Opcodes;

		/* Speedhack - skip idle loop if exists. */
		if (idle_loop_elimination_enable &&
            (Registers.PBPC == idle_loop_target_pc) && (CPU.Cycles < CPU.NextEvent))
         CPU.Cycles = CPU.NextEvent;

		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();
				}
			}


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

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

			if (CPU.Flags & SCAN_KEYS_FLAG)
				break;

		}

		Opcodes = S9xOpcodesSlow;

		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;
		}

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

			CPU.PCBase = S9xGetBasePointer(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 (Settings.SA1)
			S9xSA1MainLoop();

	#if (S9X_ACCURACY_LEVEL <= 2)
		while (CPU.Cycles >= CPU.NextEvent)
			S9xDoHEventProcessing();
	#endif
	}while(1);

	S9xPackStatus();

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