refactoring z80 if code for sms preparation

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@752 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2009-08-14 15:02:54 +00:00
parent 4010330cc0
commit c8d1e9b662
10 changed files with 354 additions and 375 deletions

View file

@ -19,7 +19,7 @@ typedef unsigned int u32;
#define UTYPES_DEFINED
#endif
extern unsigned int lastSSRamWrite; // used by serial SRAM code
extern unsigned int lastSSRamWrite; // used by serial eeprom code
#ifdef _ASM_MEMORY_C
u32 PicoRead8(u32 a);
@ -514,6 +514,7 @@ PICO_INTERNAL void PicoMemResetHooks(void)
PicoWrite16Hook = OtherWrite16End;
}
static void z80_mem_setup(void);
#ifdef EMU_M68K
static void m68k_mem_setup(void);
#endif
@ -555,6 +556,8 @@ PICO_INTERNAL void PicoMemSetup(void)
#ifdef EMU_M68K
m68k_mem_setup();
#endif
z80_mem_setup();
}
/* some nasty things below :( */
@ -880,7 +883,7 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80)
if (xcycles >= timer_b_next_oflow) \
ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 2
u32 ym2612_read_local_z80(void)
static u32 MEMH_FUNC ym2612_read_local_z80(void)
{
int xcycles = z80_cyclesDone() << 8;
@ -978,94 +981,114 @@ void ym2612_unpack_state(void)
// -----------------------------------------------------------------
// z80 memhandlers
PICO_INTERNAL unsigned char z80_read(unsigned short a)
static unsigned char MEMH_FUNC z80_md_vdp_read(unsigned short a)
{
u8 ret = 0;
// TODO?
elprintf(EL_ANOMALY, "z80 invalid r8 [%06x] %02x", a, 0xff);
return 0xff;
}
if ((a>>13)==2) // 0x4000-0x5fff (Charles MacDonald)
{
return ym2612_read_local_z80();
static unsigned char MEMH_FUNC z80_md_bank_read(unsigned short a)
{
extern unsigned int PicoReadM68k8(unsigned int a);
unsigned int addr68k;
unsigned char ret;
addr68k = Pico.m.z80_bank68k<<15;
addr68k += a & 0x7fff;
if (addr68k < Pico.romsize) {
ret = Pico.rom[addr68k^1];
goto out;
}
if (a>=0x8000)
{
extern u32 PicoReadM68k8(u32 a);
u32 addr68k;
addr68k=Pico.m.z80_bank68k<<15;
addr68k+=a&0x7fff;
elprintf(EL_ANOMALY, "z80->68k upper read [%06x] %02x", addr68k, ret);
if (PicoAHW & PAHW_MCD)
ret = PicoReadM68k8(addr68k);
else ret = PicoRead8(addr68k);
if (addr68k < Pico.romsize) { ret = Pico.rom[addr68k^1]; goto bnkend; }
elprintf(EL_ANOMALY, "z80->68k upper read [%06x] %02x", addr68k, ret);
if (PicoAHW & PAHW_MCD)
ret = PicoReadM68k8(addr68k);
else ret = PicoRead8(addr68k);
bnkend:
elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret);
return ret;
}
// should not be needed, cores should be able to access RAM themselves
if (a<0x4000) return Pico.zram[a&0x1fff];
elprintf(EL_ANOMALY, "z80 invalid r8 [%06x] %02x", a, ret);
out:
elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret);
return ret;
}
#ifndef _USE_CZ80
PICO_INTERNAL_ASM void z80_write(unsigned char data, unsigned short a)
#else
PICO_INTERNAL_ASM void z80_write(unsigned int a, unsigned char data)
#endif
static void MEMH_FUNC z80_md_ym2612_write(unsigned int a, unsigned char data)
{
if ((a>>13)==2) // 0x4000-0x5fff (Charles MacDonald)
if (PicoOpt & POPT_EN_FM)
emustatus |= ym2612_write_local(a, data, 1) & 1;
}
static void MEMH_FUNC z80_md_vdp_br_write(unsigned int a, unsigned char data)
{
// TODO: allow full VDP access
if ((a&0xfff9) == 0x7f11) // 7f11 7f13 7f15 7f17
{
if(PicoOpt&POPT_EN_FM) emustatus|=ym2612_write_local(a, data, 1) & 1;
if (PicoOpt & POPT_EN_PSG)
SN76496Write(data);
return;
}
if ((a&0xfff9)==0x7f11) // 7f11 7f13 7f15 7f17
if ((a>>8) == 0x60)
{
if(PicoOpt&POPT_EN_PSG) SN76496Write(data);
Pico.m.z80_bank68k >>= 1;
Pico.m.z80_bank68k |= data << 8;
Pico.m.z80_bank68k &= 0x1ff; // 9 bits and filled in the new top one
return;
}
if ((a>>8)==0x60)
{
Pico.m.z80_bank68k>>=1;
Pico.m.z80_bank68k|=(data&1)<<8;
Pico.m.z80_bank68k&=0x1ff; // 9 bits and filled in the new top one
return;
}
if (a>=0x8000)
{
extern void PicoWriteM68k8(u32 a,u8 d);
u32 addr68k;
addr68k=Pico.m.z80_bank68k<<15;
addr68k+=a&0x7fff;
elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, data);
if (PicoAHW & PAHW_MCD)
PicoWriteM68k8(addr68k, data);
else PicoWrite8(addr68k, data);
return;
}
// should not be needed
if (a<0x4000) { Pico.zram[a&0x1fff]=data; return; }
elprintf(EL_ANOMALY, "z80 invalid w8 [%06x] %02x", a, data);
}
#ifndef _USE_CZ80
PICO_INTERNAL unsigned short z80_read16(unsigned short a)
static void MEMH_FUNC z80_md_bank_write(unsigned int a, unsigned char data)
{
return (u16) ( (u16)z80_read(a) | ((u16)z80_read((u16)(a+1))<<8) );
extern void PicoWriteM68k8(unsigned int a, unsigned char d);
unsigned int addr68k;
addr68k = Pico.m.z80_bank68k << 15;
addr68k += a & 0x7fff;
elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, data);
if (PicoAHW & PAHW_MCD)
PicoWriteM68k8(addr68k, data);
else PicoWrite8(addr68k, data);
}
PICO_INTERNAL void z80_write16(unsigned short data, unsigned short a)
// -----------------------------------------------------------------
static unsigned char z80_md_in(unsigned short p)
{
z80_write((unsigned char) data,a);
z80_write((unsigned char)(data>>8),(u16)(a+1));
elprintf(EL_ANOMALY, "Z80 port %04x read", p);
return 0xff;
}
static void z80_md_out(unsigned short p, unsigned char d)
{
elprintf(EL_ANOMALY, "Z80 port %04x write %02x", p, d);
}
static void z80_mem_setup(void)
{
z80_map_set(z80_read_map, 0x0000, 0x1fff, Pico.zram, 0);
z80_map_set(z80_read_map, 0x2000, 0x3fff, Pico.zram, 0);
z80_map_set(z80_read_map, 0x4000, 0x5fff, ym2612_read_local_z80, 1);
z80_map_set(z80_read_map, 0x6000, 0x7fff, z80_md_vdp_read, 1);
z80_map_set(z80_read_map, 0x8000, 0xffff, z80_md_bank_read, 1);
z80_map_set(z80_write_map, 0x0000, 0x1fff, Pico.zram, 0);
z80_map_set(z80_write_map, 0x2000, 0x3fff, Pico.zram, 0);
z80_map_set(z80_write_map, 0x4000, 0x5fff, z80_md_ym2612_write, 1);
z80_map_set(z80_write_map, 0x6000, 0x7fff, z80_md_vdp_br_write, 1);
z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write, 1);
#ifdef _USE_DRZ80
drZ80.z80_in = z80_md_in;
drZ80.z80_out = z80_md_out;
#endif
#ifdef _USE_CZ80
Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (UINT32)Pico.zram); // main RAM
Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (UINT32)Pico.zram); // mirror
Cz80_Set_INPort(&CZ80, z80_md_in);
Cz80_Set_OUTPort(&CZ80, z80_md_out);
#endif
}

View file

@ -218,11 +218,16 @@ extern int z80_scanline_cycles; /* cycles done until z80_scanline */
#define cycles_68k_to_z80(x) ((x)*957 >> 11)
#define Z80_MEM_SHIFT 13
extern unsigned long z80_read_map [0x10000 >> Z80_MEM_SHIFT];
extern unsigned long z80_write_map[0x10000 >> Z80_MEM_SHIFT];
typedef unsigned char (z80_read_f)(unsigned short a);
typedef void (z80_write_f)(unsigned int a, unsigned char data);
// ---------------------------------------------------------
// main oscillator clock which controls timing
#define OSC_NTSC 53693100
// seems to be accurate, see scans from http://www.hot.ee/tmeeco/
#define OSC_PAL 53203424
struct PicoVideo
@ -369,12 +374,12 @@ typedef struct
#define Pico_mcd ((mcd_state *)Pico.rom)
// Area.c
// area.c
PICO_INTERNAL void PicoAreaPackCpu(unsigned char *cpu, int is_sub);
PICO_INTERNAL void PicoAreaUnpackCpu(unsigned char *cpu, int is_sub);
extern void (*PicoLoadStateHook)(void);
// cd/Area.c
// cd/area.c
PICO_INTERNAL int PicoCdSaveState(void *file);
PICO_INTERNAL int PicoCdLoadState(void *file);
@ -397,23 +402,23 @@ extern areaeof *areaEof;
extern areaseek *areaSeek;
extern areaclose *areaClose;
// Cart.c
// cart.c
extern void (*PicoCartUnloadHook)(void);
// Debug.c
// debug.c
int CM_compareRun(int cyc, int is_sub);
// Draw.c
// draw.c
PICO_INTERNAL void PicoFrameStart(void);
void PicoDrawSync(int to, int blank_last_line);
extern int DrawScanline;
#define MAX_LINE_SPRITES 29
extern unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES];
// Draw2.c
// draw2.c
PICO_INTERNAL void PicoFrameFull();
// Memory.c
// memory.c
PICO_INTERNAL void PicoInitPc(unsigned int pc);
PICO_INTERNAL unsigned int PicoCheckPc(unsigned int pc);
PICO_INTERNAL_ASM unsigned int PicoRead32(unsigned int a);
@ -421,29 +426,21 @@ PICO_INTERNAL void PicoMemSetup(void);
PICO_INTERNAL_ASM void PicoMemReset(void);
PICO_INTERNAL void PicoMemResetHooks(void);
PICO_INTERNAL int PadRead(int i);
PICO_INTERNAL unsigned char z80_read(unsigned short a);
#ifndef _USE_CZ80
PICO_INTERNAL_ASM void z80_write(unsigned char data, unsigned short a);
PICO_INTERNAL void z80_write16(unsigned short data, unsigned short a);
PICO_INTERNAL unsigned short z80_read16(unsigned short a);
#else
PICO_INTERNAL_ASM void z80_write(unsigned int a, unsigned char data);
#endif
PICO_INTERNAL int ym2612_write_local(unsigned int a, unsigned int d, int is_from_z80);
extern unsigned int (*PicoRead16Hook)(unsigned int a, int realsize);
extern void (*PicoWrite8Hook) (unsigned int a,unsigned int d,int realsize);
extern void (*PicoWrite16Hook)(unsigned int a,unsigned int d,int realsize);
// cd/Memory.c
// cd/memory.c
PICO_INTERNAL void PicoMemSetupCD(void);
PICO_INTERNAL_ASM void PicoMemResetCD(int r3);
PICO_INTERNAL_ASM void PicoMemResetCDdecode(int r3);
// Pico/Memory.c
// pico/memory.c
PICO_INTERNAL void PicoMemSetupPico(void);
PICO_INTERNAL unsigned int ym2612_read_local_68k(void);
// Pico.c
// pico.c
extern struct Pico Pico;
extern struct PicoSRAM SRam;
extern int PicoPadInt[2];
@ -454,23 +451,23 @@ PICO_INTERNAL int CheckDMA(void);
PICO_INTERNAL void PicoDetectRegion(void);
PICO_INTERNAL void PicoSyncZ80(int m68k_cycles_done);
// cd/Pico.c
// cd/pico.c
PICO_INTERNAL void PicoInitMCD(void);
PICO_INTERNAL void PicoExitMCD(void);
PICO_INTERNAL void PicoPowerMCD(void);
PICO_INTERNAL int PicoResetMCD(void);
PICO_INTERNAL void PicoFrameMCD(void);
// Pico/Pico.c
// pico/pico.c
PICO_INTERNAL void PicoInitPico(void);
PICO_INTERNAL void PicoReratePico(void);
// Pico/xpcm.c
// pico/xpcm.c
PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo);
PICO_INTERNAL void PicoPicoPCMReset(void);
PICO_INTERNAL void PicoPicoPCMRerate(int xpcm_rate);
// Sek.c
// sek.c
PICO_INTERNAL void SekInit(void);
PICO_INTERNAL int SekReset(void);
PICO_INTERNAL void SekState(int *data);
@ -479,7 +476,7 @@ void SekStepM68k(void);
void SekInitIdleDet(void);
void SekFinishIdleDet(void);
// cd/Sek.c
// cd/sek.c
PICO_INTERNAL void SekInitS68k(void);
PICO_INTERNAL int SekResetS68k(void);
PICO_INTERNAL int SekInterruptS68k(int irq);
@ -515,13 +512,13 @@ void ym2612_unpack_state(void);
timer_b_step = TIMER_B_TICK_ZCYCLES * 256;
// VideoPort.c
// videoport.c
PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d);
PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a);
PICO_INTERNAL_ASM unsigned int PicoVideoRead8(unsigned int a);
extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp);
// Misc.c
// misc.c
PICO_INTERNAL void SRAMWriteEEPROM(unsigned int d);
PICO_INTERNAL void SRAMUpdPending(unsigned int a, unsigned int d);
PICO_INTERNAL_ASM unsigned int SRAMReadEEPROM(void);
@ -530,7 +527,16 @@ PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count)
PICO_INTERNAL_ASM void memcpy32(int *dest, int *src, int count); // 32bit word count
PICO_INTERNAL_ASM void memset32(int *dest, int c, int count);
// cd/Misc.c
// z80 functionality wrappers
PICO_INTERNAL void z80_init(void);
PICO_INTERNAL void z80_pack(unsigned char *data);
PICO_INTERNAL void z80_unpack(unsigned char *data);
PICO_INTERNAL void z80_reset(void);
PICO_INTERNAL void z80_exit(void);
void z80_map_set(unsigned long *map, int start_addr,
int end_addr, void *func_or_mh, int is_func);
// cd/misc.c
PICO_INTERNAL_ASM void wram_2M_to_1M(unsigned char *m);
PICO_INTERNAL_ASM void wram_1M_to_2M(unsigned char *m);
@ -542,12 +548,6 @@ PICO_INTERNAL void PsndReset(void);
PICO_INTERNAL void PsndDoDAC(int line_to);
PICO_INTERNAL void PsndClear(void);
PICO_INTERNAL void PsndGetSamples(int y);
// z80 functionality wrappers
PICO_INTERNAL void z80_init(void);
PICO_INTERNAL void z80_pack(unsigned char *data);
PICO_INTERNAL void z80_unpack(unsigned char *data);
PICO_INTERNAL void z80_reset(void);
PICO_INTERNAL void z80_exit(void);
extern int PsndDacLine;
// emulation event logging
@ -595,6 +595,12 @@ extern void lprintf(const char *fmt, ...);
#define cdprintf(x...)
#endif
#if defined(__GNUC__) && !defined(ARM)
#define MEMH_FUNC __attribute__((aligned(4)))
#else
#define MEMH_FUNC
#endif
#ifdef __cplusplus
} // End of extern "C"
#endif

View file

@ -396,271 +396,3 @@ PICO_INTERNAL void PsndGetSamples(int y)
#endif
}
// -----------------------------------------------------------------
// z80 stuff
#ifdef _USE_MZ80
// memhandlers for mz80 core
unsigned char mz80_read(UINT32 a, struct MemoryReadByte *w) { return z80_read(a); }
void mz80_write(UINT32 a, UINT8 d, struct MemoryWriteByte *w) { z80_write(d, a); }
// structures for mz80 core
static struct MemoryReadByte mz80_mem_read[]=
{
{0x0000,0xffff,mz80_read},
{(UINT32) -1,(UINT32) -1,NULL}
};
static struct MemoryWriteByte mz80_mem_write[]=
{
{0x0000,0xffff,mz80_write},
{(UINT32) -1,(UINT32) -1,NULL}
};
static struct z80PortRead mz80_io_read[] ={
{(UINT16) -1,(UINT16) -1,NULL}
};
static struct z80PortWrite mz80_io_write[]={
{(UINT16) -1,(UINT16) -1,NULL}
};
int mz80_run(int cycles)
{
int ticks_pre = mz80GetElapsedTicks(0);
mz80exec(cycles);
return mz80GetElapsedTicks(0) - ticks_pre;
}
#endif
#ifdef _USE_DRZ80
struct DrZ80 drZ80;
static unsigned int DrZ80_rebasePC(unsigned short a)
{
drZ80.Z80PC_BASE = (unsigned int) Pico.zram;
return drZ80.Z80PC_BASE + a;
}
static unsigned int DrZ80_rebaseSP(unsigned short a)
{
drZ80.Z80SP_BASE = (unsigned int) Pico.zram;
return drZ80.Z80SP_BASE + a;
}
#endif
#if defined(_USE_DRZ80) || defined(_USE_CZ80)
static unsigned char z80_in(unsigned short p)
{
elprintf(EL_ANOMALY, "Z80 port %04x read", p);
return 0xff;
}
static void z80_out(unsigned short p,unsigned char d)
{
elprintf(EL_ANOMALY, "Z80 port %04x write %02x", p, d);
}
#endif
// z80 functionality wrappers
PICO_INTERNAL void z80_init(void)
{
#ifdef _USE_MZ80
struct mz80context z80;
// z80
mz80init();
// Modify the default context
mz80GetContext(&z80);
// point mz80 stuff
z80.z80Base=Pico.zram;
z80.z80MemRead=mz80_mem_read;
z80.z80MemWrite=mz80_mem_write;
z80.z80IoRead=mz80_io_read;
z80.z80IoWrite=mz80_io_write;
mz80SetContext(&z80);
#endif
#ifdef _USE_DRZ80
memset(&drZ80, 0, sizeof(struct DrZ80));
drZ80.z80_rebasePC=DrZ80_rebasePC;
drZ80.z80_rebaseSP=DrZ80_rebaseSP;
drZ80.z80_read8 =z80_read;
drZ80.z80_read16 =NULL;
drZ80.z80_write8 =z80_write;
drZ80.z80_write16 =NULL;
drZ80.z80_in =z80_in;
drZ80.z80_out =z80_out;
drZ80.z80_irq_callback=NULL;
#endif
#ifdef _USE_CZ80
memset(&CZ80, 0, sizeof(CZ80));
Cz80_Init(&CZ80);
Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (UINT32)Pico.zram); // main RAM
Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (UINT32)Pico.zram); // mirror
Cz80_Set_ReadB(&CZ80, (UINT8 (*)(UINT32 address))z80_read); // unused (hacked in)
Cz80_Set_WriteB(&CZ80, z80_write);
Cz80_Set_INPort(&CZ80, z80_in);
Cz80_Set_OUTPort(&CZ80, z80_out);
#endif
}
PICO_INTERNAL void z80_reset(void)
{
#ifdef _USE_MZ80
mz80reset();
#endif
#ifdef _USE_DRZ80
memset(&drZ80, 0, 0x54);
drZ80.Z80F = (1<<2); // set ZFlag
drZ80.Z80F2 = (1<<2); // set ZFlag
drZ80.Z80IX = 0xFFFF << 16;
drZ80.Z80IY = 0xFFFF << 16;
drZ80.Z80IM = 0; // 1?
drZ80.z80irqvector = 0xff0000; // RST 38h
drZ80.Z80PC = drZ80.z80_rebasePC(0);
drZ80.Z80SP = drZ80.z80_rebaseSP(0x2000); // 0xf000 ?
#endif
#ifdef _USE_CZ80
Cz80_Reset(&CZ80);
Cz80_Set_Reg(&CZ80, CZ80_IX, 0xffff);
Cz80_Set_Reg(&CZ80, CZ80_IY, 0xffff);
Cz80_Set_Reg(&CZ80, CZ80_SP, 0x2000);
#endif
Pico.m.z80_fakeval = 0; // for faking when Z80 is disabled
}
#if 0
static int had_irq = 0, z80_ppc, z80_ops_done = 0;
int z80_cycles_left = 0;
void z80_int(void)
{
had_irq = 1;
}
static void xfail(void)
{
printf("PC: %04x, %04x\n", Cz80_Get_Reg(&CZ80, CZ80_PC), z80_ppc);
printf("z80_ops_done done: %i\n", z80_ops_done);
exit(1);
}
int z80_run(int cycles)
{
int fail = 0;
int cdrz, ccz;
z80_cycles_left = cycles;
z80_ppc = Cz80_Get_Reg(&CZ80, CZ80_PC);
if (had_irq) {
printf("irq @ %04x\n", Cz80_Get_Reg(&CZ80, CZ80_PC));
Cz80_Set_IRQ(&CZ80, 0, HOLD_LINE);
drZ80.Z80_IRQ = 1;
had_irq = 0;
}
while (z80_cycles_left > 0)
{
ccz = Cz80_Exec(&CZ80, 1);
cdrz = 1 - DrZ80Run(&drZ80, 1);
if (drZ80.Z80_IRQ && (drZ80.Z80IF&1))
cdrz += 1 - DrZ80Run(&drZ80, 1); // cz80 processes IRQ after EI, DrZ80 does not
if (cdrz != ccz) {
printf("cycles: %i vs %i\n", cdrz, ccz);
fail = 1;
}
if (drZ80.Z80PC - drZ80.Z80PC_BASE != Cz80_Get_Reg(&CZ80, CZ80_PC)) {
printf("PC: %04x vs %04x\n", drZ80.Z80PC - drZ80.Z80PC_BASE, Cz80_Get_Reg(&CZ80, CZ80_PC));
fail = 1;
}
if (fail) xfail();
z80_ops_done++;
z80_cycles_left -= ccz;
z80_ppc = Cz80_Get_Reg(&CZ80, CZ80_PC);
}
return co - z80_cycles_left;
}
#endif
PICO_INTERNAL void z80_pack(unsigned char *data)
{
#if defined(_USE_MZ80)
struct mz80context mz80;
*(int *)data = 0x00005A6D; // "mZ"
mz80GetContext(&mz80);
memcpy(data+4, &mz80.z80clockticks, sizeof(mz80)-5*4); // don't save base&memhandlers
#elif defined(_USE_DRZ80)
*(int *)data = 0x015A7244; // "DrZ" v1
drZ80.Z80PC = drZ80.z80_rebasePC(drZ80.Z80PC-drZ80.Z80PC_BASE);
drZ80.Z80SP = drZ80.z80_rebaseSP(drZ80.Z80SP-drZ80.Z80SP_BASE);
memcpy(data+4, &drZ80, 0x54);
#elif defined(_USE_CZ80)
*(int *)data = 0x00007a43; // "Cz"
*(int *)(data+4) = Cz80_Get_Reg(&CZ80, CZ80_PC);
memcpy(data+8, &CZ80, (INT32)&CZ80.BasePC - (INT32)&CZ80);
#endif
}
PICO_INTERNAL void z80_unpack(unsigned char *data)
{
#if defined(_USE_MZ80)
if (*(int *)data == 0x00005A6D) { // "mZ" save?
struct mz80context mz80;
mz80GetContext(&mz80);
memcpy(&mz80.z80clockticks, data+4, sizeof(mz80)-5*4);
mz80SetContext(&mz80);
} else {
z80_reset();
z80_int();
}
#elif defined(_USE_DRZ80)
if (*(int *)data == 0x015A7244) { // "DrZ" v1 save?
memcpy(&drZ80, data+4, 0x54);
// update bases
drZ80.Z80PC = drZ80.z80_rebasePC(drZ80.Z80PC-drZ80.Z80PC_BASE);
drZ80.Z80SP = drZ80.z80_rebaseSP(drZ80.Z80SP-drZ80.Z80SP_BASE);
} else {
z80_reset();
drZ80.Z80IM = 1;
z80_int(); // try to goto int handler, maybe we won't execute trash there?
}
#elif defined(_USE_CZ80)
if (*(int *)data == 0x00007a43) { // "Cz" save?
memcpy(&CZ80, data+8, (INT32)&CZ80.BasePC - (INT32)&CZ80);
Cz80_Set_Reg(&CZ80, CZ80_PC, *(int *)(data+4));
} else {
z80_reset();
z80_int();
}
#endif
}
PICO_INTERNAL void z80_exit(void)
{
#if defined(_USE_MZ80)
mz80shutdown();
#endif
}
#if 1 // defined(__DEBUG_PRINT) || defined(__GP2X__) || defined(__GIZ__)
PICO_INTERNAL void z80_debug(char *dstr)
{
#if defined(_USE_DRZ80)
sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", drZ80.Z80PC-drZ80.Z80PC_BASE, drZ80.Z80SP-drZ80.Z80SP_BASE);
#elif defined(_USE_CZ80)
sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", CZ80.PC - CZ80.BasePC, CZ80.SP.W);
#endif
}
#endif

212
pico/z80if.c Normal file
View file

@ -0,0 +1,212 @@
#include "pico_int.h"
#include "sound/sn76496.h"
#define Z80_MEM_SHIFT 13
unsigned long z80_read_map [0x10000 >> Z80_MEM_SHIFT];
unsigned long z80_write_map[0x10000 >> Z80_MEM_SHIFT];
void MEMH_FUNC z80_map_set(unsigned long *map, int start_addr, int end_addr,
void *func_or_mh, int is_func)
{
unsigned long addr = (unsigned long)func_or_mh;
int mask = (1 << Z80_MEM_SHIFT) - 1;
int i;
if ((start_addr & mask) != 0 || (end_addr & mask) != mask)
elprintf(EL_STATUS|EL_ANOMALY, "z80_map_set: tried to map bad range: %04x-%04x",
start_addr, end_addr);
if (addr & 1) {
elprintf(EL_STATUS|EL_ANOMALY, "z80_map_set: ptr is not aligned: %08lx", addr);
return;
}
for (i = start_addr >> Z80_MEM_SHIFT; i <= end_addr >> Z80_MEM_SHIFT; i++)
if (is_func)
map[i] = (addr >> 1) | (1 << (sizeof(addr) * 8 - 1));
else
map[i] = (addr - (i << Z80_MEM_SHIFT)) >> 1;
}
#ifdef _USE_MZ80
// memhandlers for mz80 core
unsigned char mz80_read(UINT32 a, struct MemoryReadByte *w) { return z80_read(a); }
void mz80_write(UINT32 a, UINT8 d, struct MemoryWriteByte *w) { z80_write(d, a); }
// structures for mz80 core
static struct MemoryReadByte mz80_mem_read[]=
{
{0x0000,0xffff,mz80_read},
{(UINT32) -1,(UINT32) -1,NULL}
};
static struct MemoryWriteByte mz80_mem_write[]=
{
{0x0000,0xffff,mz80_write},
{(UINT32) -1,(UINT32) -1,NULL}
};
static struct z80PortRead mz80_io_read[] ={
{(UINT16) -1,(UINT16) -1,NULL}
};
static struct z80PortWrite mz80_io_write[]={
{(UINT16) -1,(UINT16) -1,NULL}
};
int mz80_run(int cycles)
{
int ticks_pre = mz80GetElapsedTicks(0);
mz80exec(cycles);
return mz80GetElapsedTicks(0) - ticks_pre;
}
#endif
#ifdef _USE_DRZ80
struct DrZ80 drZ80;
static unsigned int DrZ80_rebasePC(unsigned short a)
{
drZ80.Z80PC_BASE = (unsigned int) Pico.zram;
return drZ80.Z80PC_BASE + a;
}
static unsigned int DrZ80_rebaseSP(unsigned short a)
{
drZ80.Z80SP_BASE = (unsigned int) Pico.zram;
return drZ80.Z80SP_BASE + a;
}
#endif
PICO_INTERNAL void z80_init(void)
{
#ifdef _USE_MZ80
struct mz80context z80;
// z80
mz80init();
// Modify the default context
mz80GetContext(&z80);
// point mz80 stuff
z80.z80Base=Pico.zram;
z80.z80MemRead=mz80_mem_read;
z80.z80MemWrite=mz80_mem_write;
z80.z80IoRead=mz80_io_read;
z80.z80IoWrite=mz80_io_write;
mz80SetContext(&z80);
#endif
#ifdef _USE_DRZ80
memset(&drZ80, 0, sizeof(drZ80));
drZ80.z80_rebasePC=DrZ80_rebasePC;
drZ80.z80_rebaseSP=DrZ80_rebaseSP;
drZ80.z80_read8 =(void *)z80_read_map;
drZ80.z80_read16 =NULL;
drZ80.z80_write8 =(void *)z80_write_map;
drZ80.z80_write16 =NULL;
drZ80.z80_irq_callback=NULL;
#endif
#ifdef _USE_CZ80
memset(&CZ80, 0, sizeof(CZ80));
Cz80_Init(&CZ80);
Cz80_Set_ReadB(&CZ80, NULL); // unused (hacked in)
Cz80_Set_WriteB(&CZ80, NULL);
#endif
}
PICO_INTERNAL void z80_reset(void)
{
#ifdef _USE_MZ80
mz80reset();
#endif
#ifdef _USE_DRZ80
memset(&drZ80, 0, 0x54);
drZ80.Z80F = (1<<2); // set ZFlag
drZ80.Z80F2 = (1<<2); // set ZFlag
drZ80.Z80IX = 0xFFFF << 16;
drZ80.Z80IY = 0xFFFF << 16;
drZ80.Z80IM = 0; // 1?
drZ80.z80irqvector = 0xff0000; // RST 38h
drZ80.Z80PC = drZ80.z80_rebasePC(0);
drZ80.Z80SP = drZ80.z80_rebaseSP(0x2000); // 0xf000 ?
#endif
#ifdef _USE_CZ80
Cz80_Reset(&CZ80);
Cz80_Set_Reg(&CZ80, CZ80_IX, 0xffff);
Cz80_Set_Reg(&CZ80, CZ80_IY, 0xffff);
Cz80_Set_Reg(&CZ80, CZ80_SP, 0x2000);
#endif
Pico.m.z80_fakeval = 0; // for faking when Z80 is disabled
}
PICO_INTERNAL void z80_pack(unsigned char *data)
{
#if defined(_USE_MZ80)
struct mz80context mz80;
*(int *)data = 0x00005A6D; // "mZ"
mz80GetContext(&mz80);
memcpy(data+4, &mz80.z80clockticks, sizeof(mz80)-5*4); // don't save base&memhandlers
#elif defined(_USE_DRZ80)
*(int *)data = 0x015A7244; // "DrZ" v1
drZ80.Z80PC = drZ80.z80_rebasePC(drZ80.Z80PC-drZ80.Z80PC_BASE);
drZ80.Z80SP = drZ80.z80_rebaseSP(drZ80.Z80SP-drZ80.Z80SP_BASE);
memcpy(data+4, &drZ80, 0x54);
#elif defined(_USE_CZ80)
*(int *)data = 0x00007a43; // "Cz"
*(int *)(data+4) = Cz80_Get_Reg(&CZ80, CZ80_PC);
memcpy(data+8, &CZ80, (INT32)&CZ80.BasePC - (INT32)&CZ80);
#endif
}
PICO_INTERNAL void z80_unpack(unsigned char *data)
{
#if defined(_USE_MZ80)
if (*(int *)data == 0x00005A6D) { // "mZ" save?
struct mz80context mz80;
mz80GetContext(&mz80);
memcpy(&mz80.z80clockticks, data+4, sizeof(mz80)-5*4);
mz80SetContext(&mz80);
} else {
z80_reset();
z80_int();
}
#elif defined(_USE_DRZ80)
if (*(int *)data == 0x015A7244) { // "DrZ" v1 save?
memcpy(&drZ80, data+4, 0x54);
// update bases
drZ80.Z80PC = drZ80.z80_rebasePC(drZ80.Z80PC-drZ80.Z80PC_BASE);
drZ80.Z80SP = drZ80.z80_rebaseSP(drZ80.Z80SP-drZ80.Z80SP_BASE);
} else {
z80_reset();
drZ80.Z80IM = 1;
z80_int(); // try to goto int handler, maybe we won't execute trash there?
}
#elif defined(_USE_CZ80)
if (*(int *)data == 0x00007a43) { // "Cz" save?
memcpy(&CZ80, data+8, (INT32)&CZ80.BasePC - (INT32)&CZ80);
Cz80_Set_Reg(&CZ80, CZ80_PC, *(int *)(data+4));
} else {
z80_reset();
z80_int();
}
#endif
}
PICO_INTERNAL void z80_exit(void)
{
#if defined(_USE_MZ80)
mz80shutdown();
#endif
}
PICO_INTERNAL void z80_debug(char *dstr)
{
#if defined(_USE_DRZ80)
sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", drZ80.Z80PC-drZ80.Z80PC_BASE, drZ80.Z80SP-drZ80.Z80SP_BASE);
#elif defined(_USE_CZ80)
sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", CZ80.PC - CZ80.BasePC, CZ80.SP.W);
#endif
}