⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 z80.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
字号:
#include "driver.h"
#include "cpuintrf.h"
#include "z80.h"

#define INT_IRQ 0x01
#define NMI_IRQ 0x02

#define PUSH_PC() { Z80.regs.Z80SP=z80_rebaseSP(Z80.regs.Z80SP-Z80.regs.Z80SP_BASE-2); Z80.regs.z80_write16(Z80.regs.Z80PC - Z80.regs.Z80PC_BASE,Z80.regs.Z80SP - Z80.regs.Z80SP_BASE); }
/*#define PUSH_PC() { Z80.regs.Z80SP-=2; Z80.regs.z80_write16(Z80.regs.Z80PC - Z80.regs.Z80PC_BASE,Z80.regs.Z80SP); }*/

/*int Z80_ICount;*/

Z80_Regs Z80;

static unsigned int z80_rebaseSP(unsigned short address)
{
	change_pc(address);	
	Z80.regs.Z80SP_BASE=(unsigned int) OP_ROM;
	Z80.regs.Z80SP=Z80.regs.Z80SP_BASE + address;
	return (Z80.regs.Z80SP);
}

static unsigned int z80_rebasePC(unsigned short address)
{
	change_pc(address);
	Z80.regs.Z80PC_BASE = (unsigned int) OP_ROM;
	Z80.regs.Z80PC = Z80.regs.Z80PC_BASE + address;
	return (Z80.regs.Z80PC);
}

static unsigned short z80_read16(unsigned short Addr)
{
	return (((cpu_readmem16(Addr))&0xFF)|((cpu_readmem16(Addr+1)&0xff)<<8));
}

static void z80_write8(unsigned char Value,unsigned short Addr)
{
	cpu_writemem16(Addr,Value);
}

static void z80_write16(unsigned short Value,unsigned short Addr)
{
	cpu_writemem16(Addr,(unsigned char)Value&0xff);
	cpu_writemem16(Addr+1,((unsigned char)(Value>>8))&0xff);
}

static void z80_irq_callback(void)
{
	Z80.regs.Z80_IRQ = 0x00;
}

/****************************************************************************
 * Reset registers to their initial values
 ****************************************************************************/
void Z80_Reset(Z80_DaisyChain *daisy_chain)
{
	memset (&Z80, 0, sizeof(Z80_Regs));
  	Z80.regs.z80_rebasePC=z80_rebasePC;
  	Z80.regs.z80_rebaseSP=z80_rebaseSP /* 0 */;
  	Z80.regs.z80_read8   =cpu_readmem16; /* z80_read8 */
  	Z80.regs.z80_read16  =z80_read16;
  	Z80.regs.z80_write8  =z80_write8;
  	Z80.regs.z80_write16 =z80_write16;
  	Z80.regs.z80_in      =cpu_readport;
  	Z80.regs.z80_out     =cpu_writeport;
  	Z80.regs.z80_irq_callback=z80_irq_callback;
  	Z80.regs.Z80A = 0x00 <<24;
  	Z80.regs.Z80F = (1<<2); /* set ZFlag */
  	Z80.regs.Z80BC = 0x0000	<<16;
  	Z80.regs.Z80DE = 0x0000	<<16;
  	Z80.regs.Z80HL = 0x0000	<<16;
  	Z80.regs.Z80A2 = 0x00 <<24;
  	Z80.regs.Z80F2 = 1<<2;  /* set ZFlag */
  	Z80.regs.Z80BC2 = 0x0000 <<16;
  	Z80.regs.Z80DE2 = 0x0000 <<16;
  	Z80.regs.Z80HL2 = 0x0000 <<16;
  	Z80.regs.Z80IX = 0xFFFF	<<16;
  	Z80.regs.Z80IY = 0xFFFF	<<16;
	Z80.regs.Z80I = 0x00;
  	Z80.regs.Z80IM = 0x00;
  	Z80.regs.Z80_IRQ = 0x00;
  	Z80.regs.Z80IF = 0x00;
  	Z80.regs.Z80PC=Z80.regs.z80_rebasePC(0);
  	Z80.regs.Z80SP=Z80.regs.z80_rebaseSP(0xf000); /* 0xf000 */
	Z80.request_irq = Z80.service_irq = -1;

	Z80_Clear_Pending_Interrupts();
    	if (daisy_chain) {
        	while( daisy_chain->irq_param != -1 && Z80.irq_max < Z80_MAXDAISY )
        	{
            		/* set callbackhandler after reti */
			Z80.irq[Z80.irq_max] = *daisy_chain;
            		/* device reset */
			if( Z80.irq[Z80.irq_max].reset )
				Z80.irq[Z80.irq_max].reset(Z80.irq[Z80.irq_max].irq_param);
			Z80.irq_max++;
            		daisy_chain++;
        	}
    	}
}

void Z80_Cause_Interrupt(int type)
{
	/* type value :                                                            */
	/*  Z80_NMI_INT                      -> NMI request                        */
	/*  Z80_IGNORE_INT                   -> no request                         */
	/*  vector(0x00-0xff)                -> SINGLE interrupt request           */
	/*  Z80_VECTOR(device,status)        -> DaisyChain change interrupt status */
	/*      device : device number of daisy-chain link                         */
	/*      status : Z80_INT_REQ  -> interrupt request                         */
	/*               Z80_INT_IEO  -> interrupt disable output                  */

    	if (type == Z80_NMI_INT) {
	       	Z80.pending_irq |= NMI_IRQ;
	} else if (type != Z80_IGNORE_INT) {
        	if( Z80.irq_max ) {   /* daisy chain mode */
            		int device = type >> 8;
            		int state  = type & 0xff;
            		if( Z80.int_state[device] != state ) {
                		
                		/* set new interrupt status */
                		Z80.int_state[device] = state;
                		
                		/* check interrupt status */
				/* search highest interrupt request device (next interrupt device) */
				/*    and highest interrupt service device (next reti      device) */
				{
					int device;
					Z80.request_irq = Z80.service_irq = -1;

					/* search higher IRQ or IEO */
					for( device = 0 ; device < Z80.irq_max ; device ++ ) {
        					/* IEO = disable ? */
						if( Z80.int_state[device] & Z80_INT_IEO ) {
							/* if IEO is disable , masking lower IRQ */
							Z80.request_irq = -1;
							/* set highest interrupt service device */
							Z80.service_irq = device;
						}
						/* IRQ = ON ? */
						if( Z80.int_state[device] & Z80_INT_REQ )
							Z80.request_irq = device;
    					}
					/* set interrupt pending flag */
					if( Z80.request_irq >= 0 )
						Z80.pending_irq |=  INT_IRQ;
					else
						Z80.pending_irq &= ~INT_IRQ;
				}
            		}
        	} else {
        		/* single int mode */
			Z80.regs.z80irqvector = type & 0xff;
            		Z80.pending_irq |= INT_IRQ;
        	}
    	}
}

void Z80_Clear_Pending_Interrupts(void)
{
	int i;
    	/* clear irq for all devices */
    	for( i = 0 ; i < Z80_MAXDAISY ; i++ )
        	Z80.int_state[i]  = 0;
    	Z80.pending_irq = 0;
	Z80.service_irq = -1;
}


/* Set all registers to given values */
void Z80_SetRegs (Z80_Regs *Regs)
{
	memcpy(&Z80,Regs,sizeof(Z80));
	change_pc(Z80.regs.Z80PC - Z80.regs.Z80PC_BASE);
}

/* Get all registers in given buffer */
void Z80_GetRegs (Z80_Regs *Regs)
{
	memcpy(Regs,&Z80,sizeof(Z80));
}

/* Return program counter */
unsigned Z80_GetPC (void)
{
	return (Z80.regs.Z80PC - Z80.regs.Z80PC_BASE);
}

int Z80_GetPreviousPC (void)
{
	return (Z80.regs.previouspc);
}


void Interrupt(void)
{
	/* This extra check is because DrZ80 calls this function directly but does
	    not have access to the Z80.pending_irq variable.  So we check here instead. */
	if(!Z80.pending_irq) {	return; } /* If no pending ints exit */
	
	/* Check if ints enabled */						
	if ( (Z80.pending_irq & NMI_IRQ) || (Z80.regs.Z80IF&1) ) 
	{  
	
        	int irq_vector = Z80_IGNORE_INT;

		/* there isn't a valid previouspc */
		{
			extern int previouspc;
			previouspc = -1;
			Z80.regs.previouspc=-1;
		}

		/* DrZ80 Z80IF */
		/* bit1 = _IFF1 */
		/* bit2 = _IFF2 */
		/* bit3 = _HALT */
		
        	/* Check if processor was halted */
		if (Z80.regs.Z80IF&4) 
		{ 
			 Z80.regs.Z80PC=Z80.regs.z80_rebasePC(Z80.regs.Z80PC - Z80.regs.Z80PC_BASE + 1);  	/* Inc PC */
			 Z80.regs.Z80IF&= ~4; 	/* and clear halt */
		}  
		 
		if (Z80.pending_irq & NMI_IRQ) 
		{
			Z80.regs.Z80IF = (Z80.regs.Z80IF&1)<<1;  /* Save interrupt flip-flop 1 to 2 and Clear interrupt flip-flop 1 */
			PUSH_PC();
			Z80.regs.Z80PC=Z80.regs.z80_rebasePC(0x0066);
			/* reset NMI interrupt request */
			Z80.pending_irq &= ~NMI_IRQ;
		} 
		else 
		{
			/* Clear interrupt flip-flop 1 */
            		Z80.regs.Z80IF&= ~1;
			/* reset INT interrupt request */
			Z80.pending_irq &= ~INT_IRQ;
			if ( Z80.irq_max ) 
			{
                		if( Z80.request_irq >= 0 ) {
                    			irq_vector = Z80.irq[Z80.request_irq].interrupt_entry(Z80.irq[Z80.request_irq].irq_param);
                    			Z80.request_irq = -1;
                		}
            		} else {
                		irq_vector = Z80.regs.z80irqvector;
            		}
            
            		/* Interrupt mode 2. Call [Z80.I:databyte] */
			if( Z80.regs.Z80IM == 2 ) 
			{
				irq_vector = (irq_vector & 0xff) | (Z80.regs.Z80I << 8);
				PUSH_PC();
				Z80.regs.Z80PC=Z80.regs.z80_rebasePC(Z80.regs.z80_read16(irq_vector));
			} 
			else
			{
				/* Interrupt mode 1. RST 38h */
				if( Z80.regs.Z80IM == 1 ) 
				{
					PUSH_PC();
					Z80.regs.Z80PC=Z80.regs.z80_rebasePC(0x0038);
				} 
				else 
				{
					/* Interrupt mode 0. We check for CALL and JP instructions, */
					/* if neither of these were found we assume a 1 byte opcode */
					/* was placed on the databus */
					switch (irq_vector & 0xff0000) 
					{
						case 0xcd0000:	/* call */
							PUSH_PC();
						case 0xc30000:	/* jump */
							Z80.regs.Z80PC=Z80.regs.z80_rebasePC(irq_vector & 0xffff);
							break;
						default:
							irq_vector &= 0xff;
							PUSH_PC();
							Z80.regs.Z80PC=Z80.regs.z80_rebasePC(0x0038);
							break;
					}
				}
			}
		}
    	} else {
    		
    	}
}

/****************************************************************************
 * Execute IPeriod T-states. Return number of T-states really executed
 ****************************************************************************/
int Z80_Execute(int cycles)
{
	Z80_ICount = cycles;
	{
		extern int previouspc;
		previouspc = (Z80.regs.Z80PC - Z80.regs.Z80PC_BASE);
		Z80.regs.previouspc=previouspc;
	}
	if (Z80.pending_irq)
		Interrupt();
	DrZ80Run(&Z80.regs, cycles);
	change_pc(Z80.regs.Z80PC - Z80.regs.Z80PC_BASE);
	return (cycles-Z80.regs.cycles);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -