uint8 asm_S9xGetByte(uint32 Address)
{
#ifdef __debug_c_io__
	printf("gb\n");
#endif	
	return S9xGetByte(Address);	
}
示例#2
0
static uint8 dreadb(uint32 addr) {
  if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
    //$[00-3f|80-bf]:[2000-5fff]
    //do not read MMIO registers within debugger
    return 0x00;
  }
  return S9xGetByte(addr, true);
}
示例#3
0
static INLINE bool8 HDMAReadLineCount (int d)
{
	/* CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges. */

	uint8	line;

	line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address);
	CPU.Cycles += SLOW_ONE_CYCLE;

	DMA[d].LineCount = 128;

	if (!line)
	{
		DMA[d].Repeat = FALSE;

		if (DMA[d].HDMAIndirectAddressing)
		{
			if (PPU.HDMA & (0xfe << d))
			{
				DMA[d].Address++;
				CPU.Cycles += (SLOW_ONE_CYCLE << 1);
			}
			else
				CPU.Cycles += SLOW_ONE_CYCLE;

			DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address, WRAP_NONE);
			DMA[d].Address++;
		}

		DMA[d].Address++;
		HDMAMemPointers[d] = NULL;

		return (FALSE);
	}
	else
	if (line == 0x80)
		DMA[d].Repeat = TRUE;
	else
	{
		DMA[d].Repeat = !(line & 0x80);
		DMA[d].LineCount = line & 0x7f;
	}

	DMA[d].Address++;
	DMA[d].DoTransfer = TRUE;

	if (DMA[d].HDMAIndirectAddressing)
	{
		CPU.Cycles += (SLOW_ONE_CYCLE << 1);
		DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address, WRAP_NONE);
		DMA[d].Address += 2;
		HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress);
	}
	else
		HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].ABank << 16) + DMA[d].Address);

	return (TRUE);
}
示例#4
0
static uint8 S9xGetByteFree (uint32 address)
{
	int32	Cycles = CPU.Cycles;
    int32   NextEvent = CPU.NextEvent;
	uint8	byte;

    CPU.NextEvent = 0x7FFFFFFF;
	byte = S9xGetByte(address);
    CPU.NextEvent = NextEvent;
	CPU.Cycles = Cycles;

	return (byte);
}
示例#5
0
void S9xAddCheat (bool8 enable, bool8 save_current_value, 
		  uint32 address, uint8 byte)
{
    if (Cheat.num_cheats < sizeof (Cheat.c) / sizeof (Cheat. c [0]))
    {
	Cheat.c [Cheat.num_cheats].address = address;
	Cheat.c [Cheat.num_cheats].byte = byte;
	Cheat.c [Cheat.num_cheats].enabled = TRUE;
	if (save_current_value)
	{
	    Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByte (address, &CPU);
	    Cheat.c [Cheat.num_cheats].saved = TRUE;
	}
	Cheat.num_cheats++;
    }
}
示例#6
0
void S9xAddCheat (bool8 enable, bool8 save_current_value, 
		  uint32 address, uint8 byte)
{
    if (Cheat.num_cheats < sizeof (Cheat.c) / sizeof (Cheat. c [0]))
    {
	Cheat.c [Cheat.num_cheats].address = address;
	Cheat.c [Cheat.num_cheats].byte = byte;
#ifdef __MACOSX__
	Cheat.c [Cheat.num_cheats].enabled = enable;
#else
	Cheat.c [Cheat.num_cheats].enabled = TRUE;
#endif
	if (save_current_value)
	{
	    Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByte (address);
	    Cheat.c [Cheat.num_cheats].saved = TRUE;
	}
	Cheat.num_cheats++;
    }
}
示例#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 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;
	}
}
示例#9
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;
	}
}
示例#10
0
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();
}
示例#11
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);
}
示例#12
0
static uint8 S9xDoHDMA (uint8 byte)
{
	uint8 mask;
	uint32	ShiftedIBank;
	uint16	IAddr;
	bool8	temp;
	int32	tmpch;
	int d;
	struct SDMA *p;

	p = &DMA[0];

	d = 0;

	CPU.InHDMA = TRUE;
	CPU.InDMAorHDMA = TRUE;
	CPU.HDMARanInDMA = CPU.InDMA ? byte : 0;
	temp = CPU.InWRAMDMAorHDMA;
	tmpch = CPU.CurrentDMAorHDMAChannel;

	/* XXX: Not quite right... */
	CPU.Cycles += Timings.DMACPUSync;

	for ( mask = 1; mask; mask <<= 1, p++, d++)
	{
		if (byte & mask)
		{
			CPU.InWRAMDMAorHDMA = FALSE;
			CPU.CurrentDMAorHDMAChannel = d;

			if (p->HDMAIndirectAddressing)
			{
				ShiftedIBank = (p->IndirectBank << 16);
				IAddr = p->IndirectAddress;
			}
			else
			{
				ShiftedIBank = (p->ABank << 16);
				IAddr = p->Address;
			}

			if (!HDMAMemPointers[d])
				HDMAMemPointers[d] = S9xGetMemPointer(ShiftedIBank + IAddr);

			if (p->DoTransfer)
			{
				/* XXX: Hack for Uniracers, because we don't understand 
				OAM Address Invalidation */
				if (p->BAddress == 0x04 && SNESGameFixes.Uniracers)
				{
					PPU.OAMAddr = 0x10c;
					PPU.OAMFlip = 0;
				}


				if (!p->ReverseTransfer)
				{
					if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE)
					{
						/* HDMA REALLY-SLOW PATH */
						HDMAMemPointers[d] = NULL;

						#define DOBYTE(Addr, RegOff) \
							CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \
								(!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \
							S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16) (Addr))), 0x2100 + p->BAddress + (RegOff));

						DOBYTE(IAddr, 0);
						CPU.Cycles += SLOW_ONE_CYCLE;
						switch (p->TransferMode)
						{
							case 0:
								break;

							case 5:
								DOBYTE(IAddr + 1, 1);
								CPU.Cycles += SLOW_ONE_CYCLE;
								DOBYTE(IAddr + 2, 0);
								CPU.Cycles += SLOW_ONE_CYCLE;
								DOBYTE(IAddr + 3, 1);
								CPU.Cycles += SLOW_ONE_CYCLE;
								break;

							case 1:
								DOBYTE(IAddr + 1, 1);
								CPU.Cycles += SLOW_ONE_CYCLE;
								break;

							case 2:
							case 6:
								DOBYTE(IAddr + 1, 0);
								CPU.Cycles += SLOW_ONE_CYCLE;
								break;

							case 3:
							case 7:
								DOBYTE(IAddr + 1, 0);
								CPU.Cycles += SLOW_ONE_CYCLE;
								DOBYTE(IAddr + 2, 1);
								CPU.Cycles += SLOW_ONE_CYCLE;
								DOBYTE(IAddr + 3, 1);
								CPU.Cycles += SLOW_ONE_CYCLE;
								break;

							case 4:
								DOBYTE(IAddr + 1, 1);
								CPU.Cycles += SLOW_ONE_CYCLE;
								DOBYTE(IAddr + 2, 2);
								CPU.Cycles += SLOW_ONE_CYCLE;
								DOBYTE(IAddr + 3, 3);
								CPU.Cycles += SLOW_ONE_CYCLE;
								break;
						}

						#undef DOBYTE
					}
					else
					{
						CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 ||
							(!(ShiftedIBank & 0x400000) && IAddr < 0x2000));

						if (!HDMAMemPointers[d])
						{
							/* HDMA SLOW PATH */
							uint32	Addr = ShiftedIBank + IAddr;

							switch (p->TransferMode)
							{
								case 0:
									S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									break;

								case 5:
									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									Addr += 2;
									/* fall through */
								case 1:
									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									break;

								case 2:
								case 6:
									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									break;

								case 3:
								case 7:
									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									break;

								case 4:
									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									break;
							}
						}
						else
						{
							/* HDMA FAST PATH */
							switch (p->TransferMode)
							{
								case 0:
									S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									break;

								case 5:
									S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									HDMAMemPointers[d] += 2;
									/* fall through */
								case 1:
									S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									HDMAMemPointers[d] += 2;
									break;

								case 2:
								case 6:
									S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									HDMAMemPointers[d] += 2;
									break;

								case 3:
								case 7:
									S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									HDMAMemPointers[d] += 4;
									break;

								case 4:
									S9xSetPPU(*(HDMAMemPointers[d]), 0x2100 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress);
									CPU.Cycles += SLOW_ONE_CYCLE;
									HDMAMemPointers[d] += 4;
									break;
							}
						}
					}
				}

				if (p->HDMAIndirectAddressing)
					p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode];
				else
					p->Address += HDMA_ModeByteCounts[p->TransferMode];
			}

			p->DoTransfer = !p->Repeat;

			if (!--p->LineCount)
			{
				if (!HDMAReadLineCount(d))
				{
					byte &= ~mask;
					PPU.HDMAEnded |= mask;
					p->DoTransfer = FALSE;
					continue;
				}
			}
			else
				CPU.Cycles += SLOW_ONE_CYCLE;
		}
	}

	CPU.InHDMA = FALSE;
	CPU.InDMAorHDMA = CPU.InDMA;
	CPU.InWRAMDMAorHDMA = temp;
	CPU.CurrentDMAorHDMAChannel = tmpch;

	return (byte);
}
示例#13
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;
	}
}