示例#1
0
文件: psg.c 项目: denizt/hatari
/**
 * Write byte to 0xff8803. Set content of YM's data register under conditions.
 * Address 0xff8803 is a shadow version of 0xff8802, so both addresses can't be written
 * at the same time by the same instruction. This means only a .B access or
 * a movep will have a valid effect, other accesses are ignored.
 */
void PSG_ff8803_WriteByte(void)
{
	if ( nIoMemAccessSize == SIZE_BYTE )		/* byte access or movep */
	{	
		M68000_WaitState(1);			/* [NP] FIXME not 100% accurate, but gives good results */
	
		if (LOG_TRACE_LEVEL(TRACE_PSG_WRITE))
		{
			int FrameCycles, HblCounterVideo, LineCycles;
			Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
			LOG_TRACE_PRINT("ym write %x=0x%x video_cyc=%d %d@%d pc=%x instr_cycle %d\n",
					IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress],
					FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
		}
		
		PSG_Set_DataRegister ( IoMem[IoAccessCurrentAddress] );
	}

	else
	{						/* do nothing, just a trace if needed */
		if (LOG_TRACE_LEVEL(TRACE_PSG_WRITE))
		{
			int FrameCycles, HblCounterVideo, LineCycles;
			Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
			LOG_TRACE_PRINT("ym write ignored %x=0x%x video_cyc=%d %d@%d pc=%x instr_cycle %d\n",
					IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress],
					FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
		}
	}
}
示例#2
0
/**
 * This function is called after each DSP instruction when debugging is enabled.
 */
void DebugDsp_Check(void)
{
	if (bDspProfiling)
	{
		Profile_DspUpdate();
	}
	if (LOG_TRACE_LEVEL((TRACE_DSP_DISASM|TRACE_DSP_SYMBOLS)))
	{
		DebugDsp_ShowAddressInfo(DSP_GetPC());
	}
	if (nDspActiveCBs)
	{
		if (BreakCond_MatchDsp())
			DebugUI(REASON_DSP_BREAKPOINT);
	}
	if (nDspSteps)
	{
		nDspSteps -= 1;
		if (nDspSteps == 0)
			DebugUI(REASON_DSP_STEPS);
	}
	if (bHistoryEnabled)
	{
		History_AddDsp();
	}
}
示例#3
0
/**
 * Should be called before returning back emulation to tell the DSP core
 * to call us after each instruction if "real-time" debugging like
 * breakpoints has been set.
 */
void DebugDsp_SetDebugging(void)
{
	bDspProfiling = Profile_DspStart();
	nDspActiveCBs = BreakCond_BreakPointCount(true);

	if (nDspActiveCBs || nDspSteps || bDspProfiling || bHistoryEnabled
	    || LOG_TRACE_LEVEL((TRACE_DSP_DISASM|TRACE_DSP_SYMBOLS)))
		DSP_SetDebugging(true);
	else
		DSP_SetDebugging(false);
}
示例#4
0
文件: psg.c 项目: denizt/hatari
/**
 * Read byte from 0xff8801/02/03. Return 0xff.
 */
void PSG_ff880x_ReadByte(void)
{
	M68000_WaitState(1);				/* [NP] FIXME not 100% accurate, but gives good results */

	IoMem[IoAccessCurrentAddress] = 0xff;

	if (LOG_TRACE_LEVEL(TRACE_PSG_READ))
	{
		int FrameCycles, HblCounterVideo, LineCycles;
		Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
		LOG_TRACE_PRINT("ym read void %x=0x%x video_cyc=%d %d@%d pc=%x instr_cycle %d\n",
		                IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress],
		                FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
	}
}
示例#5
0
/**
 * Should be called before returning back emulation to tell the CPU core
 * to call us after each instruction if "real-time" debugging like
 * breakpoints has been set.
 */
void DebugCpu_SetDebugging(void)
{
	bCpuProfiling = Profile_CpuStart();
	nCpuActiveCBs = BreakCond_CpuBreakPointCount();

	if (nCpuActiveCBs || nCpuSteps || bCpuProfiling || History_TrackCpu()
	    || LOG_TRACE_LEVEL((TRACE_CPU_DISASM|TRACE_CPU_SYMBOLS))
	    || ConOutDevice != CONOUT_DEVICE_NONE)
	{
		M68000_SetSpecial(SPCFLAG_DEBUGGER);
		nCpuInstructions = 0;
	}	
	else
		M68000_UnsetSpecial(SPCFLAG_DEBUGGER);
}
示例#6
0
文件: psg.c 项目: denizt/hatari
/**
 * Write byte to 0xff8802. Set content of YM's data register.
 */
void PSG_ff8802_WriteByte(void)
{
//	M68000_WaitState(4);
	M68000_WaitState(1);				/* [NP] FIXME not 100% accurate, but gives good results */

	if (LOG_TRACE_LEVEL(TRACE_PSG_WRITE))
	{
		int FrameCycles, HblCounterVideo, LineCycles;
		Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
		LOG_TRACE_PRINT("ym write %x=0x%x video_cyc=%d %d@%d pc=%x instr_cycle %d\n",
				IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress],
				FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
	}

	PSG_Set_DataRegister ( IoMem[IoAccessCurrentAddress] );
}
示例#7
0
文件: psg.c 项目: denizt/hatari
/**
 * Write byte to the YM address register (usually 0xff8800). This is used
 * as a selector for when we read/write the YM data register (0xff8802).
 */
void PSG_Set_SelectRegister(Uint8 val)
{
	/* Store register used to read/write in $ff8802. This register */
	/* is 8 bits on the YM2149, this means it should not be masked */
	/* with 0xf. Instead, we keep the 8 bits, but we must ignore */
	/* read/write to ff8802 when PSGRegisterSelect >= 16 */
	PSGRegisterSelect = val;

	/* When address register is changed, a read from $ff8800 should */
	/* return the masked value of the register. We set the value here */
	/* to be returned in case PSG_Get_DataRegister is called */
	PSGRegisterReadData = PSGRegisters[PSGRegisterSelect];

	if (LOG_TRACE_LEVEL(TRACE_PSG_WRITE))
	{
		int FrameCycles, HblCounterVideo, LineCycles;
		Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
		LOG_TRACE_PRINT("ym write reg=0x%x video_cyc=%d %d@%d pc=%x instr_cycle %d\n",
		                PSGRegisterSelect, FrameCycles, LineCycles, HblCounterVideo,
		                M68000_GetPC(), CurrentInstrCycles);
	}
}
示例#8
0
/**
 * This function is called after each CPU instruction when debugging is enabled.
 */
void DebugCpu_Check(void)
{
    if (bCpuProfiling)
    {
        Profile_CpuUpdate();
    }
	if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
	{
		DebugCpu_ShowAddressInfo(M68000_GetPC());
	}
	if (nCpuActiveCBs)
	{
		if (BreakCond_MatchCpu())
			DebugUI();
	}
	if (nCpuSteps)
	{
		nCpuSteps -= 1;
		if (nCpuSteps == 0)
			DebugUI();
	}
}
示例#9
0
/**
 * This function is called after each CPU instruction when debugging is enabled.
 */
void DebugCpu_Check(void)
{
	nCpuInstructions++;
	if (bCpuProfiling)
	{
		Profile_CpuUpdate();
	}
	if (LOG_TRACE_LEVEL((TRACE_CPU_DISASM|TRACE_CPU_SYMBOLS)))
	{
		DebugCpu_ShowAddressInfo(M68000_GetPC());
	}
	if (nCpuActiveCBs)
	{
		if (BreakCond_MatchCpu())
		{
			DebugUI(REASON_CPU_BREAKPOINT);
			/* make sure we don't decrease step count
			 * below, before even even getting out of here
			 */
			if (nCpuSteps)
				nCpuSteps++;
		}
	}
	if (nCpuSteps)
	{
		nCpuSteps--;
		if (nCpuSteps == 0)
			DebugUI(REASON_CPU_STEPS);
	}
	if (History_TrackCpu())
	{
		History_AddCpu();
	}
	if (ConOutDevice != CONOUT_DEVICE_NONE)
	{
		Console_Check();
	}
}
示例#10
0
文件: psg.c 项目: denizt/hatari
/**
 * Reset variables used in PSG
 */
void PSG_Reset(void)
{
        int     i;

	if (LOG_TRACE_LEVEL(TRACE_PSG_WRITE))
	{
		int FrameCycles, HblCounterVideo, LineCycles;
		Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
		LOG_TRACE_PRINT("ym reset video_cyc=%d %d@%d pc=%x instr_cycle %d\n",
		                FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
	}

	PSGRegisterSelect = 0;
	PSGRegisterReadData = 0;
	memset(PSGRegisters, 0, sizeof(PSGRegisters));
	PSGRegisters[PSG_REG_IO_PORTA] = 0xff;			/* no drive selected + side 0 after a reset */

	/* Update sound's emulation registers */
        for ( i=0 ; i < NUM_PSG_SOUND_REGISTERS; i++ )
		Sound_WriteReg ( i , 0 );

	LastStrobe=0;
}
示例#11
0
文件: psg.c 项目: denizt/hatari
/**
 * Write byte to YM's register (0xff8802), store according to PSG select register (0xff8800)
 */
void PSG_Set_DataRegister(Uint8 val)
{
	if (LOG_TRACE_LEVEL(TRACE_PSG_WRITE))
	{
		int FrameCycles, HblCounterVideo, LineCycles;
		Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
		LOG_TRACE_PRINT("ym write data reg=0x%x val=0x%x video_cyc=%d %d@%d pc=%x instr_cycle %d\n",
		                PSGRegisterSelect, val, FrameCycles, LineCycles,
		                HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
	}

	/* Is a valid PSG register currently selected ? */
	if ( PSGRegisterSelect >= MAX_PSG_REGISTERS )
		return;					/* not valid, ignore write and do nothing */

	/* Create samples up until this point with current values */
	Sound_Update(false);

	/* When a read is made from $ff8800 without changing PSGRegisterSelect, we should return */
	/* the non masked value. */
	PSGRegisterReadData = val;			/* store non masked value for PSG_Get_DataRegister */

	/* Copy value to PSGRegisters[] */
	PSGRegisters[PSGRegisterSelect] = val;

	/* Clear unused bits for some regs */
	if ( ( PSGRegisterSelect == PSG_REG_CHANNEL_A_COARSE ) || ( PSGRegisterSelect == PSG_REG_CHANNEL_B_COARSE )
		|| ( PSGRegisterSelect == PSG_REG_CHANNEL_C_COARSE ) || ( PSGRegisterSelect == PSG_REG_ENV_SHAPE ) )
	  PSGRegisters[PSGRegisterSelect] &= 0x0f;	/* only keep bits 0 - 3 */

	else if ( ( PSGRegisterSelect == PSG_REG_CHANNEL_A_AMP ) || ( PSGRegisterSelect == PSG_REG_CHANNEL_B_AMP )
		|| ( PSGRegisterSelect == PSG_REG_CHANNEL_C_AMP ) || ( PSGRegisterSelect == PSG_REG_NOISE_GENERATOR ) )
	  PSGRegisters[PSGRegisterSelect] &= 0x1f;	/* only keep bits 0 - 4 */


	if ( PSGRegisterSelect < NUM_PSG_SOUND_REGISTERS )
	{
		/* Copy sound related registers 0..13 to the sound module's internal buffer */
		Sound_WriteReg ( PSGRegisterSelect , PSGRegisters[PSGRegisterSelect] );
	}

	else if ( PSGRegisterSelect == PSG_REG_IO_PORTA )
	{
	/*
	 * FIXME: This is only a prelimary dirty hack!
	 * Port B (Printer port) - writing here needs to be dispatched to the printer
	 * STROBE (Port A bit5) does a short LOW and back to HIGH when the char is valid
	 * To print you need to write the character byte to IOB and you need to toggle STROBE
	 * (like EmuTOS does).
	 */
		/* Printer dispatching only when printing is activated */
		if (ConfigureParams.Printer.bEnablePrinting)
		{
			/* Bit 5 - Centronics strobe? If STROBE is low and the LastStrobe was high,
					then print/transfer to the emulated Centronics port.
			 */
			if (LastStrobe && ( (PSGRegisters[PSG_REG_IO_PORTA]&(1<<5)) == 0 ))
			{
				/* Seems like we want to print something... */
				Printer_TransferByteTo(PSGRegisters[PSG_REG_IO_PORTB]);
				/* Initiate a possible GPIP0 Printer BUSY interrupt */
				MFP_InputOnChannel ( MFP_INT_GPIP0 , 0 );
				/* Initiate a possible GPIP1 Falcon ACK interrupt */
				if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
					MFP_InputOnChannel ( MFP_INT_GPIP1 , 0 );
			}
		}
		LastStrobe = PSGRegisters[PSG_REG_IO_PORTA]&(1<<5);

		/* Bit 0-2 : side and drive select */
		if ( (PSGRegisters[PSG_REG_IO_PORTA]&(1<<1)) == 0 )
		{
			/* floppy drive A is ON */
			Statusbar_SetFloppyLed(DRIVE_LED_A, LED_STATE_ON);
		}
		else
		{
			Statusbar_SetFloppyLed(DRIVE_LED_A, LED_STATE_OFF);
		}
		if ( (PSGRegisters[PSG_REG_IO_PORTA]&(1<<2)) == 0 )
		{
			/* floppy drive B is ON */
			Statusbar_SetFloppyLed(DRIVE_LED_B, LED_STATE_ON);
		}
		else
		{
			Statusbar_SetFloppyLed(DRIVE_LED_B, LED_STATE_OFF);
		}

		/* Bit 3 - Centronics as input */
		if(PSGRegisters[PSG_REG_IO_PORTA]&(1<<3))
		{
			/* FIXME: might be needed if we want to emulate sound sampling hardware */
		}
		
		/* handle Falcon specific bits in PORTA of the PSG */
		if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
		{
			/* Bit 4 - DSP reset? */
			if(PSGRegisters[PSG_REG_IO_PORTA]&(1<<4))
			{
				Log_Printf(LOG_DEBUG, "Calling DSP_Reset?\n");
#if ENABLE_DSP_EMU
				if (ConfigureParams.System.nDSPType == DSP_TYPE_EMU) {
					DSP_Reset();
				}
#endif
			}
			/* Bit 6 - Internal Speaker control */
			if(PSGRegisters[PSG_REG_IO_PORTA]&(1<<6))
			{
				/*Log_Printf(LOG_DEBUG, "Falcon: Internal Speaker state\n");*/
				/* FIXME: add code to handle? (if we want to emulate the speaker at all? */
			}
			/* Bit 7 - Reset IDE? */
			if(PSGRegisters[PSG_REG_IO_PORTA]&(1<<7))
			{
				Log_Printf(LOG_DEBUG, "Falcon: Reset IDE subsystem\n");
				/* FIXME: add code to handle IDE reset */
			}
		}
	
	}
}
示例#12
0
文件: vdi.c 项目: libretro/hatari
/**
 * Check whether this is VDI/AES call and see if we need to re-direct
 * it to our own routines. Return true if VDI_Complete() function
 * needs to be called on OS call exit, otherwise return false.
 *
 * We enter here with Trap #2, so D0 tells which OS call it is (VDI/AES)
 * and D1 is pointer to VDI/AES vectors, i.e. Control, Intin, Ptsin etc...
 */
bool VDI_AES_Entry(void)
{
	Uint16 call = Regs[REG_D0];
	Uint32 TablePtr = Regs[REG_D1];

#if ENABLE_TRACING
	/* AES call? */
	if (call == 0xC8)
	{
		if (!STMemory_ValidArea(TablePtr, 24))
		{
			Log_Printf(LOG_WARN, "AES call failed due to invalid parameter block address 0x%x+%i\n", TablePtr, 24);
			return false;
		}
		/* store values for debugger "info aes" command */
		AESControl = STMemory_ReadLong(TablePtr);
		AESGlobal  = STMemory_ReadLong(TablePtr+4);
		AESIntin   = STMemory_ReadLong(TablePtr+8);
		AESIntout  = STMemory_ReadLong(TablePtr+12);
		AESAddrin  = STMemory_ReadLong(TablePtr+16);
		AESAddrout = STMemory_ReadLong(TablePtr+20);
		AESOpCode  = STMemory_ReadWord(AESControl);
		if (LOG_TRACE_LEVEL(TRACE_OS_AES))
		{
			AES_OpcodeInfo(TraceFile, AESOpCode);
		}
		/* using same special opcode trick doesn't work for
		 * both VDI & AES as AES functions can be called
		 * recursively and VDI calls happen inside AES calls.
		 */
		return false;
	}
#endif

	/* VDI call? */
	if (call == 0x73)
	{
		if (!STMemory_ValidArea(TablePtr, 20))
		{
			Log_Printf(LOG_WARN, "VDI call failed due to invalid parameter block address 0x%x+%i\n", TablePtr, 20);
			return false;
		}
		/* store values for extended VDI resolution handling
		 * and debugger "info vdi" command
		 */
		VDIControl = STMemory_ReadLong(TablePtr);
		VDIIntin   = STMemory_ReadLong(TablePtr+4);
		VDIPtsin   = STMemory_ReadLong(TablePtr+8);
		VDIIntout  = STMemory_ReadLong(TablePtr+12);
		VDIPtsout  = STMemory_ReadLong(TablePtr+16);
		VDIOpCode  = STMemory_ReadWord(VDIControl);
#if ENABLE_TRACING
		{
		Uint16 subcode = STMemory_ReadWord(VDIControl+2*5);
		LOG_TRACE(TRACE_OS_VDI, "VDI call %3hd/%3hd (%s)\n",
			  VDIOpCode, subcode,
			  VDI_Opcode2Name(VDIOpCode, subcode));
		}
#endif
		/* Only workstation open needs to be handled at trap return */
		return bUseVDIRes && VDI_isWorkstationOpen(VDIOpCode);
	}

	LOG_TRACE((TRACE_OS_VDI|TRACE_OS_AES), "Trap #2 with D0 = 0x%hX\n", call);
	return false;
}