DRZ80 support

This commit is contained in:
Francisco José García García 2019-12-28 13:00:07 +01:00
parent ce39a255e9
commit 82292fc0a8
6 changed files with 1155 additions and 1118 deletions

41
DrZ80.h
View File

@ -2,23 +2,23 @@
* DrZ80 Version 1.0
* Z80 Emulator by Reesy
* Copyright 2005 Reesy
*
*
* This file is part of DrZ80.
*
*
* DrZ80 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* DrZ80 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DrZ80; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*
*/
#ifdef __cplusplus
@ -31,10 +31,10 @@ extern "C" {
extern int DrZ80Ver; /* Version number of library */
struct DrZ80
{
{
unsigned int Z80PC; /*0x00 - PC Program Counter (Memory Base + PC) */
unsigned int Z80A; /*0x04 - A Register: 0xAA------ */
unsigned int Z80F; /*0x08 - F Register: 0xFF------ */
unsigned int Z80F; /*0x08 - F Register: 0x------FF */
unsigned int Z80BC; /*0x0C - BC Registers: 0xBBCC---- */
unsigned int Z80DE; /*0x10 - DE Registers: 0xDDEE---- */
unsigned int Z80HL; /*0x14 - HL Registers: 0xHHLL---- */
@ -45,32 +45,33 @@ struct DrZ80
unsigned int Z80IY; /*0x28 - IY Index Register */
unsigned int Z80I; /*0x2C - I Interrupt Register */
unsigned int Z80A2; /*0x30 - A' Register: 0xAA------ */
unsigned int Z80F2; /*0x34 - F' Register: 0xFF------ */
unsigned int Z80F2; /*0x34 - F' Register: 0x------FF */
unsigned int Z80BC2; /*0x38 - B'C' Registers: 0xBBCC---- */
unsigned int Z80DE2; /*0x3C - D'E' Registers: 0xDDEE---- */
unsigned int Z80HL2; /*0x40 - H'L' Registers: 0xHHLL---- */
int cycles; /* Cycles pending to be executed yet */
int previouspc; /* Previous PC */
unsigned char Z80_IRQ; /*0x44 - Set IRQ Number */
unsigned char Z80IF; /*0x48 - Interrupt Flags: bit1=_IFF1, bit2=_IFF2, bit3=_HALT */
unsigned char Z80IM; /*0x4C - Set IRQ Mode */
unsigned char spare; /*0x4C - N/A */
unsigned int z80irqvector; /*0x38 - Set IRQ Vector i.e. 0xFF=RST */
unsigned int Z80HL2; /*0x40 - H'L' Registers: 0xHHLL---- */
int cycles; /*0x44 - Cycles pending to be executed yet */
int previouspc; /*0x48 - Previous PC */
unsigned char Z80_IRQ; /*0x4C - Set IRQ Number (must be halfword aligned) */
unsigned char Z80IF; /*0x4D - Interrupt Flags: bit0=_IFF1, bit1=_IFF2, bit2=_HALT, b3=NMI */
unsigned char Z80IM; /*0x4E - Set IRQ Mode */
unsigned char spare; /*0x4F - N/A */
unsigned int z80irqvector; /*0x50 - Set IRQ Vector i.e. 0xFF=RST */
void (*z80_irq_callback )(void);
void (*z80_write8 )(unsigned char d,unsigned short a);
void (*z80_write16 )(unsigned short d,unsigned short a);
void (*z80_write8 )(unsigned char d,unsigned short a);
void (*z80_write16 )(unsigned short d,unsigned short a);
unsigned char (*z80_in)(unsigned short p);
void (*z80_out )(unsigned short p,unsigned char d);
unsigned char (*z80_read8)(unsigned short a);
unsigned short (*z80_read16)(unsigned short a);
unsigned int (*z80_rebaseSP)(unsigned short new_sp);
unsigned int (*z80_rebasePC)(unsigned short new_pc);
unsigned int bla;
};
extern void DrZ80Run(struct DrZ80 *pcy,unsigned int cyc);
extern int DrZ80Run(struct DrZ80 *pcy,unsigned int cyc);
#endif
#ifdef __cplusplus
} /* End of extern "C" */
#endif
#endif

1904
DrZ80.s

File diff suppressed because it is too large Load Diff

View File

@ -20,27 +20,25 @@
#include "DrZ80_support.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;*/
#define NMI_IRQ 0x08
Z80_Regs Z80;
#define z80_int() Z80.regs.Z80_IRQ = INT_IRQ
#define z80_nmi() Z80.regs.Z80IF |= NMI_IRQ
static unsigned int z80_rebaseSP(unsigned short address)
{
//Z80.regs.Z80SP_BASE = (unsigned int)&mainram[0x3000];
Z80.regs.Z80SP = Z80.regs.Z80SP_BASE + address;
return (Z80.regs.Z80SP);
Z80.regs.Z80SP_BASE = (unsigned int)&mainram[0x3000];
Z80.regs.Z80SP = Z80.regs.Z80SP_BASE + address;
return Z80.regs.Z80SP_BASE + address;
}
static unsigned int z80_rebasePC(unsigned short address)
{
//Z80.regs.Z80PC_BASE = (unsigned int)&mainram[0x3000];
Z80.regs.Z80PC = Z80.regs.Z80PC_BASE + address;
return (Z80.regs.Z80PC);
Z80.regs.Z80PC_BASE = (unsigned int)&mainram[0x3000];
Z80.regs.Z80PC = Z80.regs.Z80PC_BASE + address;
return Z80.regs.Z80PC_BASE + address;
}
static void z80_irq_callback(void)
@ -55,7 +53,6 @@ static void z80_irq_callback(void)
void Z80_Reset(void)
{
memset (&Z80, 0, sizeof(Z80_Regs));
#ifdef DRZ80
Z80.regs.z80_rebasePC=z80_rebasePC;
Z80.regs.z80_rebaseSP=z80_rebaseSP /* 0 */;
Z80.regs.z80_read8 =z80MemReadB; /* z80_read8 */
@ -64,246 +61,33 @@ void Z80_Reset(void)
Z80.regs.z80_write16 =DrZ80ngpMemWriteW;
Z80.regs.z80_in =DrZ80ngpPortReadB;
Z80.regs.z80_out =DrZ80ngpPortWriteB;
//Z80.regs.z80_irq_callback=z80_irq_callback;
Z80.regs.z80_irq_callback=z80_irq_callback;
Z80.regs.Z80BC = 0013;
Z80.regs.Z80DE = 0x00D8;
Z80.regs.Z80HL = 0x014D;
/*
Z80.regs.Z80A = 0x00 <<24;
Z80.regs.Z80F = (1<<2); // set ZFlag
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(0x0000);
//Z80.regs.Z80SP=Z80.regs.z80_rebaseSP(0xFFFE); /* 0xf000 */
Z80.regs.Z80SP_BASE = (unsigned int)&mainram[0x3000];
Z80.regs.Z80SP = Z80.regs.Z80SP_BASE + 0xFFFE;
Z80.regs.Z80PC_BASE = (unsigned int)&mainram[0x3000];
Z80.regs.Z80PC = Z80.regs.Z80PC_BASE + 0x0000;
Z80.request_irq = Z80.service_irq = -1;
Z80.regs.Z80PC=Z80.regs.z80_rebasePC(0);
Z80.regs.Z80SP=Z80.regs.z80_rebaseSP(0xFFFE);
Z80_Clear_Pending_Interrupts();
#endif
}
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
if (type == Z80_NMI_INT)
{
/* single int mode */
Z80.regs.z80irqvector = type & 0xff;
Z80.pending_irq |= INT_IRQ;
}
}
z80_nmi();
}
else if (type != Z80_IGNORE_INT)
{
z80_int();
}
}
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
{
}
Z80.regs.Z80_IRQ = 0x00;
}
/****************************************************************************
@ -312,12 +96,7 @@ void Interrupt(void)
extern "C" int Z80_Execute(int cycles)
{
Z80.regs.cycles = cycles;
//Z80.regs.previouspc=(Z80.regs.Z80PC - Z80.regs.Z80PC_BASE);
if (Z80.pending_irq)
Interrupt();
DrZ80Run(&Z80.regs, cycles);
//change_pc(Z80.regs.Z80PC - Z80.regs.Z80PC_BASE);
return cycles;// (cycles-Z80.regs.cycles);
}

View File

@ -6,42 +6,17 @@ extern "C" {
#endif
//#include "osd_cpu.h"
//#include "cpuintrf.h"
#include "DrZ80.h"
/* daisy-chain link */
typedef struct {
void (*reset)(int); /* reset callback */
int (*interrupt_entry)(int); /* entry callback */
void (*interrupt_reti)(int); /* reti callback */
int irq_param; /* callback paramater */
} Z80_DaisyChain;
#define Z80_MAXDAISY 4 /* maximum of daisy chan device */
#define Z80_INT_REQ 0x01 /* interrupt request mask */
#define Z80_INT_IEO 0x02 /* interrupt disable mask(IEO) */
#define Z80_VECTOR(device,state) (((device)<<8)|(state))
/****************************************************************************/
/* The Z80 registers. HALT is set to 1 when the CPU is halted, the refresh */
/* register is calculated as follows: refresh=(Regs.R&127)|(Regs.R2&128) */
/****************************************************************************/
typedef struct {
struct DrZ80 regs;
int pending_irq;
int irq_max; /* number of daisy chain devices */
int request_irq; /* daisy chain next request device */
int service_irq; /* daisy chain next reti handling device */
int int_state[Z80_MAXDAISY];
Z80_DaisyChain irq[Z80_MAXDAISY];
} Z80_Regs;
/*extern int Z80_ICount; // T-state count */
extern Z80_Regs Z80;
//#define Z80_ICount (Z80.regs.cycles)
#define Z80_IGNORE_INT -1 /* Ignore interrupt */
#define Z80_NMI_INT -2 /* Execute NMI */
@ -51,7 +26,7 @@ extern unsigned Z80_GetPC (void); /* Get program counter */
extern int Z80_GetPreviousPC (void);
extern void Z80_GetRegs (Z80_Regs *Regs); /* Get registers */
extern void Z80_SetRegs (Z80_Regs *Regs); /* Set registers */
//extern void Z80_Reset (Z80_DaisyChain *daisy_chain);
extern void Z80_Reset(void);
extern int Z80_Execute(int cycles); /* Execute cycles T-States - returns number of cycles actually run */
extern int Z80_Interrupt(void);

View File

@ -167,6 +167,7 @@ else ifeq ($(platform),vita)
ASFLAGS += -mcpu=cortex-a9
STATIC_LINKING := 1
LIBS :=
DRZ80:=1
# Nintendo Game Cube
else ifeq ($(platform), ngc)

View File

@ -15,6 +15,9 @@
//////////////////////////////////////////////////////////////////////
#include "cz80.h"
#ifdef DRZ80
#include "DrZ80_support.h"
#endif
#include "neopopsound.h"
#include <string.h>
@ -47,10 +50,13 @@ struct race_state_0x11
u32 gpr[23];
/* Z80 Registers */
#ifdef CZ80
cz80_struc RACE_cz80_struc;
u32 PC_offset;
s32 Z80_ICount;
#elif DRZ80
Z80_Regs Z80;
#endif
/* Sound */
int sndCycles;
SoundChip toneChip;
@ -80,10 +86,14 @@ struct race_state_0x10 /* Older state format */
u8 f_dash;
u32 gpr[23];
//Z80 Registers
//Z80 Registers
#ifdef CZ80
cz80_struc RACE_cz80_struc;
u32 PC_offset;
s32 Z80_ICount;
#elif DRZ80
Z80_Regs Z80;
#endif
//Sound Chips
int sndCycles;
@ -157,6 +167,7 @@ static int state_store(race_state_t *rs)
rs->gpr[i++] = gen_regsXNSP;
/* Z80 Registers */
#ifdef CZ80
extern cz80_struc *RACE_cz80_struc;
extern s32 Z80_ICount;
int size_of_z80 =
@ -164,6 +175,10 @@ static int state_store(race_state_t *rs)
memcpy(&rs->RACE_cz80_struc, RACE_cz80_struc, size_of_z80);
rs->Z80_ICount = Z80_ICount;
rs->PC_offset = Cz80_Get_PC(RACE_cz80_struc);
#elif DRZ80
extern Z80_Regs Z80;
memcpy(&rs->Z80, &Z80, sizeof(Z80));
#endif
/* Sound */
extern int sndCycles;
@ -226,6 +241,7 @@ static int state_restore(race_state_t *rs)
gen_regsXNSP = rs->gpr[i++];
/* Z80 Registers */
#ifdef CZ80
extern cz80_struc *RACE_cz80_struc;
extern s32 Z80_ICount;
int size_of_z80 =
@ -234,6 +250,10 @@ static int state_restore(race_state_t *rs)
memcpy(RACE_cz80_struc, &rs->RACE_cz80_struc, size_of_z80);
Z80_ICount = rs->Z80_ICount;
Cz80_Set_PC(RACE_cz80_struc, rs->PC_offset);
#elif DRZ80
extern Z80_Regs Z80;
memcpy(&Z80, &rs->Z80, sizeof(Z80));
#endif
/* Sound */
extern int sndCycles;
@ -385,17 +405,22 @@ static int state_restore_0x10(FILE *stream)
gen_regsSP = rs.gpr[i++];
gen_regsXSSP = rs.gpr[i++];
gen_regsXNSP = rs.gpr[i++];
//Z80 Registers
#ifdef CZ80
extern cz80_struc *RACE_cz80_struc;
extern s32 Z80_ICount;
int size_of_z80 =
(u32)(&(RACE_cz80_struc->CycleSup)) - (u32)(&(RACE_cz80_struc->BC));
memcpy(RACE_cz80_struc, &rs.RACE_cz80_struc, size_of_z80);
Z80_ICount = rs.Z80_ICount;
Cz80_Set_PC(RACE_cz80_struc, rs.PC_offset);
#elif DRZ80
extern Z80_Regs Z80;
memcpy(&Z80, &rs.Z80, sizeof(Z80));
#endif
//Sound Chips
extern int sndCycles;
sndCycles = rs.sndCycles;