mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
8.4 KiB
272 lines
8.4 KiB
/* Emulation of the Z80 CPU with hooks into the other parts of xz80.
|
|
* Copyright (C) 1994 Ian Collier.
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include<stdio.h>
|
|
#include "zxcc.h"
|
|
|
|
#define parity(a) (partable[a])
|
|
|
|
unsigned char partable[256]={
|
|
4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4,
|
|
0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0,
|
|
0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0,
|
|
4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4,
|
|
0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0,
|
|
4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4,
|
|
4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4,
|
|
0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0,
|
|
0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0,
|
|
4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4,
|
|
4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4,
|
|
0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0,
|
|
4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4,
|
|
0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0,
|
|
0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0,
|
|
4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4
|
|
};
|
|
|
|
#ifdef DEBUG
|
|
// Avoid name conflict with built-in log math function
|
|
#define log z80_log
|
|
|
|
static unsigned short breakpoint=0;
|
|
static unsigned int breaks=0;
|
|
|
|
static void inline log(fp,name,val)
|
|
FILE *fp;
|
|
char *name;
|
|
unsigned short val;
|
|
{
|
|
int i;
|
|
fprintf(fp,"%s=%04X ",name,val);
|
|
for(i=0;i<8;i++,val++)fprintf(fp," %02X",fetch(val));
|
|
putc('\n',fp);
|
|
}
|
|
#endif
|
|
|
|
void mainloop(word spc, word ssp){
|
|
register unsigned char a, f, b, c, d, e, h, l;
|
|
unsigned char r, a1, f1, b1, c1, d1, e1, h1, l1, i, iff1, iff2, im;
|
|
register unsigned short pc;
|
|
unsigned short ix, iy, sp;
|
|
register unsigned long tstates;
|
|
register unsigned int radjust;
|
|
register unsigned char ixoriy, new_ixoriy;
|
|
unsigned char intsample;
|
|
register unsigned char op;
|
|
#ifdef DEBUG
|
|
char flags[9];
|
|
int bit;
|
|
FILE *fp=0;
|
|
register unsigned short af2=0,bc2=0,de2=0,hl2=0,ix2=0,iy2=0,sp2=0;
|
|
register unsigned char i2=0;
|
|
/*unsigned char *memory=memptr[0];*/
|
|
struct _next {unsigned char bytes[8];} *next;
|
|
unsigned short BC, DE, HL, AF;
|
|
|
|
fputs("Press F11 to log\n",stderr);
|
|
#endif
|
|
a=f=b=c=d=e=h=l=a1=f1=b1=c1=d1=e1=h1=l1=i=r=iff1=iff2=im=0;
|
|
ixoriy=new_ixoriy=0;
|
|
ix=iy=0;
|
|
pc=spc;
|
|
sp=ssp;
|
|
tstates=radjust=0;
|
|
while(1){
|
|
ixoriy=new_ixoriy;
|
|
new_ixoriy=0;
|
|
#ifdef DEBUG
|
|
next=(struct _next *)&fetch(pc);
|
|
BC=bc;DE=de;HL=hl;AF=(a<<8)|f;
|
|
if(fp && !ixoriy){
|
|
log(fp,"pc",pc);
|
|
if(sp!=sp2)log(fp,"sp",sp2=sp);
|
|
if(iy!=iy2)log(fp,"iy",iy2=iy);
|
|
if(ix!=ix2)log(fp,"ix",ix2=ix);
|
|
if(hl!=hl2)log(fp,"hl",hl2=hl);
|
|
if(de!=de2)log(fp,"de",de2=de);
|
|
if(bc!=bc2)log(fp,"bc",bc2=bc);
|
|
if(((a<<8)|f)!=af2){
|
|
af2=(a<<8)|f;
|
|
strcpy(flags,"SZ H VNC");
|
|
for(bit=0;bit<8;bit++)if(!(f&(1<<(7-bit))))flags[bit]=' ';
|
|
fprintf(fp,"af=%04X %s\n",af2,flags);
|
|
}
|
|
if(i!=i2)fprintf(fp,"ir=%02X%02X\n",i2=i,r);
|
|
putc('\n',fp);
|
|
}
|
|
if(pc==breakpoint && pc)
|
|
breaks++; /* some code at which to set a breakpoint */
|
|
a=AF>>8; f=AF; h=HL>>8; l=HL; d=DE>>8; e=DE; b=BC>>8; c=BC;
|
|
#endif
|
|
/*
|
|
{
|
|
static int tr = 1;
|
|
static int id = 0;
|
|
// static byte b = 0;
|
|
//
|
|
// if (pc == 0x1177) tr = 1;
|
|
// if (pc == 0x1185) tr = 0;
|
|
if (tr >= 1) ++id;
|
|
if (tr >= 1) printf("%d: PC=%04x %02x AF=%02x:%02x BC=%04x DE=%04x HL=%04x IX=%04x IY=%04x\n",
|
|
id, pc, fetch(pc), a,f, bc, de, hl, ix, iy);
|
|
}
|
|
*/
|
|
intsample=1;
|
|
op=fetch(pc);
|
|
pc++;
|
|
radjust++;
|
|
switch(op){
|
|
#include "z80ops.h"
|
|
}
|
|
/***
|
|
* ZXCC doesn't do interrupts at all, so all this is commented out
|
|
if(tstates>=int_cycles && intsample){
|
|
tstates-=int_cycles;
|
|
frames++;
|
|
// Carry out X-related tasks (including waiting for timer
|
|
// signal if necessary)
|
|
switch(interrupt()){
|
|
case Z80_quit:
|
|
#ifdef DEBUG
|
|
if(fp)fclose(fp);
|
|
#endif
|
|
return;
|
|
case Z80_NMI:
|
|
if(fetch(pc)==0x76)pc++;
|
|
iff2=iff1;
|
|
iff1=0;
|
|
// The Z80 performs a machine fetch cycle for 5 Tstates
|
|
// but ignores the result. It takes a further 10 Tstates
|
|
// to jump to the NMI routine at 0x66.
|
|
tstates+=15;
|
|
push2(pc);
|
|
pc=0x66;
|
|
break;
|
|
case Z80_reset:
|
|
a=f=b=c=d=e=h=l=a1=f1=b1=c1=d1=e1=
|
|
h1=l1=i=r=iff1=iff2=im=0;
|
|
ix=iy=sp=pc=0;
|
|
radjust=0;
|
|
break;
|
|
#ifdef DEBUG
|
|
case Z80_log:
|
|
if(fp){
|
|
fclose(fp);
|
|
fp=0;
|
|
fputs("Logging turned off\n",stderr);
|
|
} else {
|
|
fp=fopen(config.log,"a");
|
|
if(fp)fprintf(stderr,"Logging to file %s\n",config.log);
|
|
else perror(config.log);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case Z80_load:
|
|
stopwatch();
|
|
if(snapload()){
|
|
a=snapa;
|
|
f=snapf;
|
|
b=snapb;
|
|
c=snapc;
|
|
d=snapd;
|
|
e=snape;
|
|
h=snaph;
|
|
l=snapl;
|
|
a1=snapa1;
|
|
f1=snapf1;
|
|
b1=snapb1;
|
|
c1=snapc1;
|
|
d1=snapd1;
|
|
e1=snape1;
|
|
h1=snaph1;
|
|
l1=snapl1;
|
|
iff1=snapiff1;
|
|
iff2=snapiff2;
|
|
i=snapi;
|
|
r=snapr;
|
|
radjust=r;
|
|
im=snapim;
|
|
ix=snapix;
|
|
iy=snapiy;
|
|
sp=snapsp;
|
|
pc=snappc;
|
|
}
|
|
startwatch(1);
|
|
break;
|
|
case Z80_save:
|
|
r=(r&0x80)|(radjust&0x7f);
|
|
snapa=a;
|
|
snapf=f;
|
|
snapb=b;
|
|
snapc=c;
|
|
snapd=d;
|
|
snape=e;
|
|
snaph=h;
|
|
snapl=l;
|
|
snapa1=a1;
|
|
snapf1=f1;
|
|
snapb1=b1;
|
|
snapc1=c1;
|
|
snapd1=d1;
|
|
snape1=e1;
|
|
snaph1=h1;
|
|
snapl1=l1;
|
|
snapiff1=iff1;
|
|
snapiff2=iff2;
|
|
snapi=i;
|
|
snapr=r;
|
|
snapim=im;
|
|
snapix=ix;
|
|
snapiy=iy;
|
|
snapsp=sp;
|
|
snappc=pc;
|
|
snapsave();
|
|
startwatch(1);
|
|
break;
|
|
|
|
}
|
|
if(iff1){
|
|
#ifdef DEBUG
|
|
if(fp)fprintf(fp,"Interrupt (im=%d)\n\n",im);
|
|
#endif
|
|
if(fetch(pc)==0x76)pc++;
|
|
iff1=iff2=0;
|
|
tstates+=5; // accompanied by an input from the data bus //
|
|
switch(im){
|
|
case 0: // IM 0 //
|
|
case 1: // undocumented //
|
|
case 2: // IM 1 //
|
|
// there is little to distinguish between these cases //
|
|
tstates+=8;
|
|
push2(pc);
|
|
pc=0x38;
|
|
break;
|
|
case 3: // IM 2 //
|
|
tstates+=14;
|
|
{
|
|
int addr=fetch2((i<<8)|0xff);
|
|
push2(pc);
|
|
pc=addr;
|
|
}
|
|
}
|
|
}
|
|
}*/
|
|
}
|
|
}
|
|
|