/****************************************************************************/ /* Beebem - (c) David Alan Gilbert 1994 */ /* ------------------------------------ */ /* This program may be distributed freely within the following restrictions:*/ /* */ /* 1) You may not charge for this program or for any part of it. */ /* 2) This copyright message must be distributed with all copies. */ /* 3) This program must be distributed complete with source code. Binary */ /* only distribution is not permitted. */ /* 4) The author offers no warrenties, or guarentees etc. - you use it at */ /* your own risk. If it messes something up or destroys your computer */ /* thats YOUR problem. */ /* 5) You may use small sections of code from this program in your own */ /* applications - but you must acknowledge its use. If you plan to use */ /* large sections then please ask the author. */ /* */ /* If you do not agree with any of the above then please do not use this */ /* program. */ /* Please report any problems to the author at gilbertd@cs.man.ac.uk */ /****************************************************************************/ /* 6502 core - 6502 emulator core - David Alan Gilbert 16/10/94 */ // // // 4 Feb 97 MHG all opcodes supported // // #include #include #include #include "6502core.h" #include "beebmem.h" #include "disc8271.h" #include "sysvia.h" #include "uservia.h" #include "video.h" #include "sound.h" extern int DumpAfterEach; void do_sound(void); void check_op(int a); CycleCountT TotalCycles=0; static int ProgramCounter; static int Accumulator,XReg,YReg; static unsigned char StackReg,PSR; #define AC Accumulator #define XR XReg #define YR YReg #define SET_SIGN(src) ( ((src)&0x80) ? PSR|=FlagN:PSR&=~FlagN) #define SET_ZERO(src) ( ((src)==0) ? PSR|=FlagZ:PSR&=~FlagZ) #define SET_CARRY(src) ( (src) ? PSR|=FlagC:PSR&=~FlagC) #define SET_OVERFLOW(src) ( (src) ? PSR|=FlagV:PSR&=~FlagV) #define IF_SIGN() (PSR & flagN) #define IF_ZERO() (PSR & FlagZ) #define IF_CARRY() (PSR & FlagC) #define IF_DECIMAL() (PSR & FlagD) #define STORE(a,b) BEEBWRITEMEM_FAST(a,b) #define LOAD(a) BEEBREADMEM_FAST(a) #define SP StackReg unsigned char intStatus=0; /* bit set (nums in IRQ_Nums) if interrupt being caused */ unsigned char NMIStatus=0; /* bit set (nums in NMI_Nums) if NMI being caused */ unsigned int NMILock=0; /* Well I think NMI's are maskable - to stop repeated NMI's - the lock is released when an RTI is done */ typedef int int16; void u_stoshr (unsigned int val, int16 address, unsigned int index) { val &= (((address >> 8) + 1) & 0xff); if (((address & 0xff) + index) > 0xff) address = val; STORE ((address + index), val); } /* Stats */ int Stats[256]; enum PSRFlags { FlagC=1, FlagZ=2, FlagI=4, FlagD=8, FlagB=16, FlagV=64, FlagN=128 }; /* Note how GETCFLAG is special since being bit 0 we don't need to test it to get a clean 0/1 */ #define GETCFLAG ((PSR & FlagC)) #define GETZFLAG ((PSR & FlagZ)>0) #define GETIFLAG ((PSR & FlagI)>0) #define GETDFLAG ((PSR & FlagD)>0) #define GETBFLAG ((PSR & FlagB)>0) #define GETVFLAG ((PSR & FlagV)>0) #define GETNFLAG ((PSR & FlagN)>0) /* Types for internal function arrays */ typedef void (*InstrHandlerFuncType)(int16 Operand); typedef int16 (*AddrModeHandlerFuncType)(int WantsAddr); static int CyclesTable[]={ 7,6,0,0,0,3,5,0,3,2,2,0,0,4,6,0, /* 0 */ 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, /* 1 */ 6,6,0,0,3,3,5,0,4,2,2,0,4,4,6,0, /* 2 */ 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, /* 3 */ 6,6,0,0,0,3,5,0,3,2,2,0,3,4,6,0, /* 4 */ 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, /* 5 */ 6,6,0,0,0,3,5,0,4,2,2,0,5,4,6,0, /* 6 */ 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, /* 7 */ 0,6,0,0,3,3,3,0,2,0,2,0,4,4,4,0, /* 8 */ 2,6,0,0,4,4,4,0,2,5,2,0,0,5,0,0, /* 9 */ 2,6,2,0,3,3,3,0,2,2,2,0,4,4,4,0, /* a */ 2,5,0,0,4,4,4,0,2,4,2,0,4,4,4,0, /* b */ 2,6,0,0,3,3,5,0,2,2,2,0,4,4,6,0, /* c */ 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, /* d */ 2,6,0,0,3,3,5,0,2,2,2,0,4,4,6,0, /* e */ 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0 /* f */ }; /* CyclesTable */ /* The number of cycles to be used by the current instruction - exported to allow fernangling by memory subsystem */ unsigned int Cycles; /* A macro to speed up writes - uses a local variable called 'tmpaddr' */ #define FASTWRITE(addr,val) tmpaddr=addr; if (tmpaddr<0x8000) BEEBWRITEMEM_DIRECT(tmpaddr,val) else BeebWriteMem(tmpaddr,val); /* Get a two byte address from the program counter, and then post inc the program counter */ #define GETTWOBYTEFROMPC(var) \ var=WholeRam[ProgramCounter]; \ var|=(WholeRam[ProgramCounter+1]<<8); \ ProgramCounter+=2; /*----------------------------------------------------------------------------*/ inline int SignExtendByte(signed char in) { /*if (in & 0x80) return(in | 0xffffff00); else return(in); */ /* I think this should sign extend by virtue of the casts - gcc does anyway - the code above will definitly do the trick */ return((int)in); } /* SignExtendByte */ /*----------------------------------------------------------------------------*/ /* Set the Z flag if 'in' is 0, and N if bit 7 is set - leave all other bits */ /* untouched. */ static void SetPSRZN(const unsigned char in) { PSR&=~(FlagZ | FlagN); PSR|=((in==0)<<1) | (in & 128); }; /* SetPSRZN */ /*----------------------------------------------------------------------------*/ /* Note: n is 128 for true - not 1 */ static void SetPSR(int mask,int c,int z,int i,int d,int b, int v, int n) { PSR&=~mask; PSR|=c | (z<<1) | (i<<2) | (d<<3) | (b<<4) | (v<<6) | n; } /* SetPSR */ /*----------------------------------------------------------------------------*/ /* NOTE!!!!! n is 128 or 0 - not 1 or 0 */ static void SetPSRCZN(int c,int z, int n) { PSR&=~(FlagC | FlagZ | FlagN); PSR|=c | (z<<1) | n; } /* SetPSRCZN */ /*----------------------------------------------------------------------------*/ void DumpRegs(void) { static char FlagNames[]="CZIDB-VNczidb-vn"; int FlagNum; fprintf(stderr," PC=0x%x A=0x%x X=0x%x Y=0x%x S=0x%x PSR=0x%x=", ProgramCounter,Accumulator,XReg,YReg,StackReg,PSR); for(FlagNum=0;FlagNum<8;FlagNum++) fputc(FlagNames[FlagNum+8*((PSR & (1<>8) & 255); Push(topush & 255); } /* PushWord */ /*----------------------------------------------------------------------------*/ static int16 PopWord() { int16 RetValue; RetValue=Pop(); RetValue|=(Pop()<<8); return(RetValue); } /* PopWord */ /*----------------------------------------------------------------------------*/ /* Sets 2^8 result for carry */ static int16 BCDAdd(int16 in1,int16 in2) { int16 result,hn; int WasCarried=((in1 | in2) & 256)>0; int TmpCarry=0; result=(in1 & 0xf)+(in2 & 0xf); if (result>9) { result&=0xf; result+=6; result&=0xf; TmpCarry=1; } hn=(in1 &0xf0)+(in2 &0xf0)+(TmpCarry?0x10:0); if (hn>0x9f) { hn&=0xf0; hn+=0x60; hn&=0xf0; WasCarried|=1; } return(result | hn | (WasCarried*256)); } /* BCDAdd */ /*----------------------------------------------------------------------------*/ /* Sets 2^8 result for borrow */ static int16 BCDSubtract(int16 in1,int16 in2) { int16 result,hn; int WasBorrowed=((in1 | in2) & 256)>0; int TmpBorrow=0; result=(in1 & 0xf)-(in2 & 0xf); if (result<0) { result&=0xf; result-=6; result&=0xf; TmpBorrow=1; } hn=(in1 &0xf0)-(in2 &0xf0)-(TmpBorrow?0x10:0); if (hn <0) { hn&=0xf0; hn-=0x60; hn&=0xf0; WasBorrowed|=1; } return(result | hn | (WasBorrowed*256)); } /* BCDSubtract */ /*-------------------------------------------------------------------------*/ /* Relative addressing mode handler */ static int16 RelAddrModeHandler_Data(void) { int EffectiveAddress; /* For branches - is this correct - i.e. is the program counter incremented at the correct time? */ EffectiveAddress=SignExtendByte((signed char)WholeRam[ProgramCounter++]); EffectiveAddress+=ProgramCounter; return(EffectiveAddress); } /* RelAddrModeHandler */ /*----------------------------------------------------------------------------*/ static void ADCInstrHandler(int16 operand) { /* NOTE! Not sure about C and V flags */ int TmpResultV,TmpResultC; if (!GETDFLAG) { TmpResultC=Accumulator+operand+GETCFLAG; TmpResultV=(signed char)Accumulator+(signed char)operand+GETCFLAG; Accumulator=TmpResultC & 255; SetPSR(FlagC | FlagZ | FlagV | FlagN, (TmpResultC & 256)>0,Accumulator==0,0,0,0,((Accumulator & 128)>0) ^ (TmpResultV<0),(Accumulator & 128)); } else { TmpResultC=BCDAdd(Accumulator,operand); TmpResultC=BCDAdd(TmpResultC,GETCFLAG); Accumulator=TmpResultC & 255; SetPSR(FlagC | FlagZ | FlagV | FlagN, (TmpResultC & 256)>0,Accumulator==0,0,0,0,((Accumulator & 128)>0) ^ ((TmpResultC & 256)>0),(Accumulator & 128)); } } /* ADCInstrHandler */ /*----------------------------------------------------------------------------*/ static void ANDInstrHandler(int16 operand) { Accumulator=Accumulator & operand; PSR&=~(FlagZ | FlagN); PSR|=((Accumulator==0)<<1) | (Accumulator & 128); } /* ANDInstrHandler */ static void ASLInstrHandler(int16 address) { unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); newVal=(((unsigned int)oldVal)<<1); BEEBWRITEMEM_FAST(address,newVal); SetPSRCZN((oldVal & 128)>0, newVal==0,newVal & 128); } /* ASLInstrHandler */ static void ASLORAInstrHandler(int16 address) { unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); newVal=(((unsigned int)oldVal)<<1); newVal|=Accumulator; BEEBWRITEMEM_FAST(address,newVal); SetPSRCZN((oldVal & 128)>0, newVal==0,newVal & 128); } /* ASLInstrHandler */ static void ASLInstrHandler_Acc(void) { unsigned char oldVal,newVal; /* Accumulator */ oldVal=Accumulator; Accumulator=newVal=(((unsigned int)Accumulator)<<1); SetPSRCZN((oldVal & 128)>0, newVal==0,newVal & 128); } /* ASLInstrHandler_Acc */ static void BCCInstrHandler(void) { if (!GETCFLAG) { ProgramCounter=RelAddrModeHandler_Data(); Cycles++; } else ProgramCounter++; } /* BCCInstrHandler */ static void BCSInstrHandler(void) { if (GETCFLAG) { ProgramCounter=RelAddrModeHandler_Data(); Cycles++; } else ProgramCounter++; } /* BCSInstrHandler */ static void BEQInstrHandler(void) { if (GETZFLAG) { ProgramCounter=RelAddrModeHandler_Data(); Cycles++; } else ProgramCounter++; } /* BEQInstrHandler */ static void BITInstrHandler(int16 operand) { PSR&=~(FlagZ | FlagN | FlagV); /* z if result 0, and NV to top bits of operand */ PSR|=(((Accumulator & operand)==0)<<1) | (operand & 192); } /* BITInstrHandler */ static void BMIInstrHandler(void) { if (GETNFLAG) { ProgramCounter=RelAddrModeHandler_Data(); Cycles++; } else ProgramCounter++; } /* BMIInstrHandler */ static void BNEInstrHandler(void) { if (!GETZFLAG) { ProgramCounter=RelAddrModeHandler_Data(); Cycles++; } else ProgramCounter++; } /* BNEInstrHandler */ static void BPLInstrHandler(void) { if (!GETNFLAG) { ProgramCounter=RelAddrModeHandler_Data(); Cycles++; } else ProgramCounter++; }; /* BPLInstrHandler */ static void BRKInstrHandler(void) { PushWord(ProgramCounter+1); SetPSR(FlagB,0,0,0,0,1,0,0); /* Set B before pushing */ Push(PSR); SetPSR(FlagI,0,0,1,0,0,0,0); /* Set I after pushing - see Birnbaum */ ProgramCounter=BeebReadMem(0xfffe) | (BeebReadMem(0xffff)<<8); } /* BRKInstrHandler */ static void BVCInstrHandler(void) { if (!GETVFLAG) { ProgramCounter=RelAddrModeHandler_Data(); Cycles++; } else ProgramCounter++; } /* BVCInstrHandler */ static void BVSInstrHandler(void) { if (GETVFLAG) { ProgramCounter=RelAddrModeHandler_Data(); Cycles++; } else ProgramCounter++; } /* BVSInstrHandler */ static void CMPInstrHandler(int16 operand) { /* NOTE! Should we consult D flag ? */ unsigned char result=Accumulator-operand; SetPSRCZN(Accumulator>=operand,Accumulator==operand,result & 128); } /* CMPInstrHandler */ static void CPXInstrHandler(int16 operand) { unsigned char result=(XReg-operand); SetPSRCZN(XReg>=operand,XReg==operand,result & 128); } /* CPXInstrHandler */ static void CPYInstrHandler(int16 operand) { unsigned char result=(YReg-operand); SetPSRCZN(YReg>=operand,YReg==operand,result & 128); } /* CPYInstrHandler */ static void DECInstrHandler(int16 address) { unsigned char val; val=BEEBREADMEM_FAST(address); val=(val-1); BEEBWRITEMEM_FAST(address,val); SetPSRZN(val); } /* DECInstrHandler */ static void DEXInstrHandler(void) { XReg=(XReg-1) & 255; SetPSRZN(XReg); } /* DEXInstrHandler */ static void EORInstrHandler(int16 operand) { Accumulator^=operand; SetPSRZN(Accumulator); } /* EORInstrHandler */ static void INCInstrHandler(int16 address) { unsigned char val; val=BEEBREADMEM_FAST(address); val=(val+1) & 255; BEEBWRITEMEM_FAST(address,val); SetPSRZN(val); } /* INCInstrHandler */ static void INXInstrHandler(void) { XReg+=1; XReg&=255; SetPSRZN(XReg); } /* INXInstrHandler */ static void JSRInstrHandler(int16 address) { PushWord(ProgramCounter-1); ProgramCounter=address; } /* JSRInstrHandler */ static void LDAInstrHandler(int16 operand) { Accumulator=operand; SetPSRZN(Accumulator); } /* LDAInstrHandler */ static void LDXInstrHandler(int16 operand) { XReg=operand; SetPSRZN(XReg); } /* LDXInstrHandler */ static void LDYInstrHandler(int16 operand) { YReg=operand; SetPSRZN(YReg); } /* LDYInstrHandler */ static void LSRInstrHandler(int16 address) { unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); newVal=(((unsigned int)oldVal)>>1); BEEBWRITEMEM_FAST(address,newVal); SetPSRCZN((oldVal & 1)>0, newVal==0,0); } /* LSRInstrHandler */ static void LSRInstrHandler_Acc(void) { unsigned char oldVal,newVal; /* Accumulator */ oldVal=Accumulator; Accumulator=newVal=(((unsigned int)Accumulator)>>1) & 255; SetPSRCZN((oldVal & 1)>0, newVal==0,0); } /* LSRInstrHandler_Acc */ static void ORAInstrHandler(int16 operand) { Accumulator=Accumulator | operand; SetPSRZN(Accumulator); } /* ORAInstrHandler */ static void ROLInstrHandler(int16 address) { unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); newVal=((unsigned int)oldVal<<1) & 254; newVal+=GETCFLAG; BEEBWRITEMEM_FAST(address,newVal); SetPSRCZN((oldVal & 128)>0,newVal==0,newVal & 128); } /* ROLInstrHandler */ static void ROLInstrHandler_Acc(void) { unsigned char oldVal,newVal; oldVal=Accumulator; newVal=((unsigned int)oldVal<<1) & 254; newVal+=GETCFLAG; Accumulator=newVal; SetPSRCZN((oldVal & 128)>0,newVal==0,newVal & 128); } /* ROLInstrHandler_Acc */ static void ROLANDInstrHandler(int16 address) { unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); newVal=((unsigned int)oldVal<<1) & 254; newVal+=GETCFLAG; Accumulator&=newVal; BEEBWRITEMEM_FAST(address,newVal); newVal=Accumulator; SetPSRCZN((oldVal & 128)>0,newVal==0,newVal & 128); } /* ROLInstrHandler */ static void RORInstrHandler(int16 address) { unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); newVal=((unsigned int)oldVal>>1) & 127; newVal+=GETCFLAG*128; BEEBWRITEMEM_FAST(address,newVal); SetPSRCZN(oldVal & 1,newVal==0,newVal & 128); } /* RORInstrHandler */ static void RORInstrHandler_Acc(void) { unsigned char oldVal,newVal; oldVal=Accumulator; newVal=((unsigned int)oldVal>>1) & 127; newVal+=GETCFLAG*128; Accumulator=newVal; SetPSRCZN(oldVal & 1,newVal==0,newVal & 128); } /* RORInstrHandler_Acc */ static void SBCInstrHandler(int16 operand) { /* NOTE! Not sure about C and V flags */ int TmpResultV,TmpResultC; if (!GETDFLAG) { TmpResultV=(signed char)Accumulator-(signed char)operand-(1-GETCFLAG); TmpResultC=Accumulator-operand-(1-GETCFLAG); Accumulator=TmpResultC & 255; SetPSR(FlagC | FlagZ | FlagV | FlagN, TmpResultC>=0,Accumulator==0,0,0,0, ((Accumulator & 128)>0) ^ ((TmpResultV & 256)!=0),(Accumulator & 128)); } else { /* BCD subtract - note: V is probably duff*/ TmpResultC=BCDSubtract(Accumulator,operand); if (!GETCFLAG) TmpResultC=BCDSubtract(TmpResultC,0x01); Accumulator=TmpResultC & 0xff; SetPSR(FlagC | FlagZ | FlagV | FlagN, (TmpResultC & 256)==0, Accumulator==0, 0,0,0,((Accumulator & 128)>0) ^ ((TmpResultC & 256)>0), Accumulator & 0x80); } } /* SBCInstrHandler */ static void STXInstrHandler(int16 address) { BEEBWRITEMEM_FAST(address,XReg); } /* STXInstrHandler */ static void STYInstrHandler(int16 address) { BEEBWRITEMEM_FAST(address,YReg); } /* STYInstrHandler */ void error(char *t1,char *t2); static void BadInstrHandler(unsigned char a) { char str[128]; #if 0 printf("bad opcode %x\n",a); fprintf(stderr,"Bad instruction handler called:\n"); DumpRegs(); fprintf(stderr,"Dumping main memory\n"); beebmem_dumpstate(); abort(); #endif sprintf(str,"Unreconised 6502 opcode: 0x%x\n",a); error(str,""); } /* BadInstrHandler */ /*-------------------------------------------------------------------------*/ /* Absolute addressing mode handler */ static int16 AbsAddrModeHandler_Data(void) { int FullAddress; /* Get the address from after the instruction */ GETTWOBYTEFROMPC(FullAddress) /* And then read it */ return(BEEBREADMEM_FAST(FullAddress)); } /* AbsAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Absolute addressing mode handler */ static int16 AbsAddrModeHandler_Address(void) { int FullAddress; /* Get the address from after the instruction */ GETTWOBYTEFROMPC(FullAddress) /* And then read it */ return(FullAddress); } /* AbsAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Zero page addressing mode handler */ static int16 ZeroPgAddrModeHandler_Address(void) { return(WholeRam[ProgramCounter++]); } /* ZeroPgAddrModeHandler_Address */ /*-------------------------------------------------------------------------*/ /* Indexed with X preinc addressing mode handler */ static int16 IndXAddrModeHandler_Data(void) { unsigned char ZeroPageAddress; int EffectiveAddress; ZeroPageAddress=(WholeRam[ProgramCounter++]+XReg) & 255; EffectiveAddress=WholeRam[ZeroPageAddress] | (WholeRam[ZeroPageAddress+1]<<8); return(BEEBREADMEM_FAST(EffectiveAddress)); } /* IndXAddrModeHandler_Data */ /*-------------------------------------------------------------------------*/ /* Indexed with X preinc addressing mode handler */ static int16 IndXAddrModeHandler_Address(void) { unsigned char ZeroPageAddress; int EffectiveAddress; ZeroPageAddress=(WholeRam[ProgramCounter++]+XReg) & 255; EffectiveAddress=WholeRam[ZeroPageAddress] | (WholeRam[ZeroPageAddress+1]<<8); return(EffectiveAddress); } /* IndXAddrModeHandler_Address */ /*-------------------------------------------------------------------------*/ /* Indexed with Y postinc addressing mode handler */ static int16 IndYAddrModeHandler_Data(void) { int EffectiveAddress; unsigned char ZPAddr=WholeRam[ProgramCounter++]; EffectiveAddress=WholeRam[ZPAddr]+YReg; EffectiveAddress+=(WholeRam[ZPAddr+1]<<8); return(BEEBREADMEM_FAST(EffectiveAddress)); } /* IndYAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Indexed with Y postinc addressing mode handler */ static int16 IndYAddrModeHandler_Address(void) { int EffectiveAddress; unsigned char ZPAddr=WholeRam[ProgramCounter++]; EffectiveAddress=WholeRam[ZPAddr]+YReg; EffectiveAddress+=(WholeRam[ZPAddr+1]<<8); return(EffectiveAddress); } /* IndYAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Zero page wih X offset addressing mode handler */ static int16 ZeroPgXAddrModeHandler_Data(void) { int EffectiveAddress; EffectiveAddress=(WholeRam[ProgramCounter++]+XReg) & 255; return(WholeRam[EffectiveAddress]); } /* ZeroPgXAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Zero page wih X offset addressing mode handler */ static int16 ZeroPgXAddrModeHandler_Address(void) { int EffectiveAddress; EffectiveAddress=(WholeRam[ProgramCounter++]+XReg) & 255; return(EffectiveAddress); } /* ZeroPgXAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Absolute with X offset addressing mode handler */ static int16 AbsXAddrModeHandler_Data(void) { int EffectiveAddress; GETTWOBYTEFROMPC(EffectiveAddress); EffectiveAddress+=XReg; EffectiveAddress&=0xffff; return(BEEBREADMEM_FAST(EffectiveAddress)); } /* AbsXAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Absolute with X offset addressing mode handler */ static int16 AbsXAddrModeHandler_Address(void) { int EffectiveAddress; GETTWOBYTEFROMPC(EffectiveAddress) EffectiveAddress+=XReg; EffectiveAddress&=0xffff; return(EffectiveAddress); } /* AbsXAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Absolute with Y offset addressing mode handler */ static int16 AbsYAddrModeHandler_Data(void) { int EffectiveAddress; GETTWOBYTEFROMPC(EffectiveAddress) EffectiveAddress+=YReg; return(BEEBREADMEM_FAST(EffectiveAddress)); } /* AbsYAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Absolute with Y offset addressing mode handler */ static int16 AbsYAddrModeHandler_Address(void) { int EffectiveAddress; GETTWOBYTEFROMPC(EffectiveAddress) EffectiveAddress+=YReg; return(EffectiveAddress); } /* AbsYAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Indirect addressing mode handler */ static int16 IndAddrModeHandler_Address(void) { /* For jump indirect only */ int VectorLocation; int EffectiveAddress; GETTWOBYTEFROMPC(VectorLocation) EffectiveAddress=BEEBREADMEM_FAST(VectorLocation); EffectiveAddress|=BEEBREADMEM_FAST(VectorLocation+1) << 8; return(EffectiveAddress); } /* IndAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Zero page with Y offset addressing mode handler */ static int16 ZeroPgYAddrModeHandler_Data(void) { int EffectiveAddress; EffectiveAddress=(WholeRam[ProgramCounter++]+YReg) & 255; return(WholeRam[EffectiveAddress]); } /* ZeroPgYAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Zero page with Y offset addressing mode handler */ static int16 ZeroPgYAddrModeHandler_Address(void) { int EffectiveAddress; EffectiveAddress=(WholeRam[ProgramCounter++]+YReg) & 255; return(EffectiveAddress); } /* ZeroPgYAddrModeHandler */ /*-------------------------------------------------------------------------*/ /* Initialise 6502core */ void Init6502core(void) { ProgramCounter=BeebReadMem(0xfffc) | (BeebReadMem(0xfffd)<<8); Accumulator=XReg=YReg=0; /* For consistancy of execution */ StackReg=0xff; /* Initial value ? */ PSR=FlagI; /* Interrupts off for starters */ intStatus=0; NMIStatus=0; NMILock=0; } /* Init6502core */ #include "via.h" /*-------------------------------------------------------------------------*/ void DoInterrupt(void) { PushWord(ProgramCounter); Push(PSR & ~FlagB); ProgramCounter=BeebReadMem(0xfffe) | (BeebReadMem(0xffff)<<8); SetPSR(FlagI,0,0,1,0,0,0,0); } /* DoInterrupt */ /*-------------------------------------------------------------------------*/ void DoNMI(void) { /*cerr << "Doing NMI\n"; */ NMILock=1; PushWord(ProgramCounter); Push(PSR); ProgramCounter=BeebReadMem(0xfffa) | (BeebReadMem(0xfffb)<<8); SetPSR(FlagI,0,0,1,0,0,0,0); /* Normal interrupts should be disabled during NMI ? */ } /* DoNMI */ static void ANCInstrHandler(int16 operand) { unsigned char oldval; oldval=operand & Accumulator; Accumulator=oldval; SetPSRZN(Accumulator); } /* LDAInstrHandler */ // // BAD OPCODE JAMS THE MACHINE // static void STOPi() { } // // ANC: LDA+AND // A = ( A & #data) // 0B // IMM // static void ANCi(int16 data) { Accumulator=data & Accumulator; SetPSRZN(Accumulator); } // NO OPERATION static void NOPi(int16 a) { } // // 82,c2,e2 // static void NOPSi(int16 a) { } // // RMW - ASL+ORA - SHIFT & OR with Accum // 03, 07, 0f, 13, 17, 1b, 1f // INDX, ZP, ABS, INDY, ZPX, ABSY, ABSX // static void SLOi(int16 address) { /* src = asl(src); AC = ora(src); */ unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); // LOAD val from adress newVal=(((unsigned int)oldVal)<<1); // // newVal|=Accumulator; // ORA Accumulator|=newVal; // ORA BEEBWRITEMEM_FAST(address,newVal); // STORE VALUE SetPSRCZN((oldVal & 128)>0, newVal==0,newVal & 128); } // // ASR: // // A= (A & #data) >> 1 // // 4B // IMM // static void ASRi(int16 data) { unsigned char oldVal,newVal; oldVal=Accumulator; newVal=oldVal & data; newVal=(((unsigned int)newVal)>>1); Accumulator=newVal; SetPSRCZN((oldVal & 1)>0, newVal==0,0); } // // RLA: ROL + AND // // 23, 27, 2F, 33, 37, 3B, 3F // INDX, ZP, ABS, INDY, ZPX, ABSY, ABSX // static void RLAi(int16 address) { /* src = rol(src); AC = and(src); */ unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); // LOAD val from adress newVal=((unsigned int)oldVal<<1) & 254; newVal+=GETCFLAG; Accumulator&=newVal; // newVal&=Accumulator; BEEBWRITEMEM_FAST(address,newVal); // STORE VALUE SetPSRCZN((oldVal & 128)>0,newVal==0,newVal & 128); } // // SRE: LSR + EOR // // 43, 47, 4F, 53, 57, 5B, 5F // INDX, ZP, ABS, INDY, ZPX, ABSY, ABSX // static void SREi(int16 address) { /* src = lsr(src); AC = eor(src); */ unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); newVal=(((unsigned int)oldVal)>>1); newVal^=Accumulator; BEEBWRITEMEM_FAST(address,newVal); SetPSRCZN((oldVal & 1)>0, newVal==0,0); } // // RRA: ROR+ADC // // INDX, ZP, ABS, INDY, ZPX, ABSY, ABSX // 63, 67, 6F, 73, 77, 7B, 7F // static void RRAi(int16 address) { /* src = ror(src); AC = adc(src); * the real operation discovered by msmakela * ADC only does the BCD fixup */ unsigned char oldVal,newVal; oldVal=BEEBREADMEM_FAST(address); newVal=((unsigned int)oldVal>>1) & 127; newVal+=GETCFLAG*128; BEEBWRITEMEM_FAST(address,newVal); SetPSRCZN(oldVal & 1,newVal==0,newVal & 128); } // // ARR: AND+ROR // // 6B // IMM // static void ARRi(int16 data) { /* src= (A & #data) A=(src>>1) */ unsigned char oldVal,newVal; oldVal=Accumulator & data; newVal=((unsigned int)oldVal>>1) & 127; newVal+=GETCFLAG*128; Accumulator=newVal; SetPSRCZN(oldVal & 1,newVal==0,newVal & 128); } // // ANE: // A= (A | EE) & X & #data // 8B // IMM // static void ANEi(int16 data) { Accumulator=(Accumulator | 0xEE) & XReg & data; SetPSRZN(Accumulator); } // // Store X and A // 83,87,8f,97 // static void SAXi(int16 address) { unsigned char oldVal,newVal; newVal=Accumulator & XReg; BEEBWRITEMEM_FAST(address,newVal); } // // 93, 9f // INDY, ABSY // STORE A & X // static void SHAi(int16 address) { int16 src = (AC & XR); u_stoshr (src, address, YR);; } // // 9B // SP = A & X // static void SHSi() { int16 src = (AC & XR); SP = src; /* SHS */ ; } // // 9C // static void SHYi(int16 p2) { unsigned int src = YR; u_stoshr (src, p2, XR);; } // // 9E // static void SHXi(int16 p2) { unsigned int src = XR; u_stoshr (src, p2, YR);; } // // LOAD // a3,a7,af,b3,b7,bf // static void LAXi(int16 src) { SET_SIGN (src); SET_ZERO (src); AC = XR = (src);; } // // LOAD // bb // static void LASi(int16 p2) { unsigned int src = (SP & p2); SET_SIGN (src); SET_ZERO (src); AC = XR = SP = (src); } // // //c3,c7,cf,d3,d7,db,df // static void DCPi(int16 p2) { unsigned int src = LOAD (p2); /* cmp(--src & 0xff)); */ src = (src - 1) & 0xff; /* DEC+CMP */ SET_CARRY (AC >= src); SET_SIGN (AC - src); SET_ZERO (AC != src); STORE (p2, (src));; } // // Load X and A with A & #data // ab // static void LXAi(int16 p1) { unsigned int src = (AC & p1); SET_SIGN (src); SET_ZERO (src); AC = XR = (src);; } // // // cb // LOAD static void SBXi(int16 src) { src = (AC & XR) - src; /* Carry is ignored (CMP) */ /* Overflow flag may be affected */ SET_CARRY (src < 0x100); src &= 0xff; /* No decimal mode */ SET_SIGN (src); SET_ZERO (src); XR = (src);; } // // eb // static void SBCi(int16 data) { SBCInstrHandler(data); } // ISB: // // INC + SBC // e3,e7,ef,f3,f7,fb,ff // RMW // static void ISBi(int16 p2) { unsigned int src = LOAD (p2); unsigned int temp; /* src = ++src & 0xff; AC = sbc(src); */ src = ((src + 1) & 0xff); /* INC+SBC */ temp = AC - src - (IF_CARRY ()? 0 : 1); SET_SIGN (temp); SET_ZERO (temp & 0xff); /* Sign and Zero are invalid in decimal mode */ SET_OVERFLOW (((AC ^ temp) & 0x80) && ((AC ^ src) & 0x80)); if (IF_DECIMAL ()) { if (((AC & 0xf) + (IF_CARRY ()? 1 : 0)) < (src & 0xf)) temp -= 6; if (temp > 0x99) temp -= 0x60; } SET_CARRY (temp < 0x100); AC = temp; /* src saved */ STORE (p2, (src));; } #define IMPLIED 0 #define IMMEDIATE WholeRam[ProgramCounter++] #define ZP ZeroPgAddrModeHandler_Address() #define ZPX ZeroPgXAddrModeHandler_Address() #define ZPY ZeroPgXAddrModeHandler_Address() #define ABS AbsAddrModeHandler_Address() #define ABSX AbsXAddrModeHandler_Address() #define ABSY AbsYAddrModeHandler_Address() #define INDX IndXAddrModeHandler_Address() #define INDY IndYAddrModeHandler_Address() /*-------------------------------------------------------------------------*/ /* Execute one 6502 instruction, move program counter on */ void Exec6502Instruction(void) { static int CurrentInstruction; static int tmpaddr; static int OldNMIStatus; int loop; for(loop=0;loop<512;loop++) { /* Read an instruction and post inc program couter */ CurrentInstruction=WholeRam[ProgramCounter++]; /*cout << "Fetch at " << hex << (ProgramCounter-1) << " giving 0x" << CurrentInstruction << dec << "\n"; */ Cycles=CyclesTable[CurrentInstruction]; // check_op(CurrentInstruction); // if (Cycles==0) // { // printf("[%x]op 0x%x %d\n",ProgramCounter,CurrentInstruction,CurrentInstruction); // Cycles=4; // } /*Stats[CurrentInstruction]++; */ switch (CurrentInstruction) { //------------------------------------------------------------------------------------------- case 0x00: BRKInstrHandler(); break; case 0x01: ORAInstrHandler(IndXAddrModeHandler_Data()); break; case 0x02: //illegal STOPi(); break; case 3: // MHG SLOi(INDX); break; case 4: // MHG NOPi(ZP); break; case 0x05: ORAInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0x06: ASLInstrHandler(ZeroPgAddrModeHandler_Address()); break; case 0x07: // MHG SLOi(ZP); break; case 0x08: Push(PSR); /* PHP */ break; case 0x09: ORAInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0x0a: ASLInstrHandler_Acc(); break; case 0x0b: // MHG ANCi(IMMEDIATE); break; case 0x0c: // MHG NOPi(ABS); break; case 0x0d: ORAInstrHandler(AbsAddrModeHandler_Data()); break; case 0x0e: ASLInstrHandler(AbsAddrModeHandler_Address()); break; case 0x0f: //MHG SLO SLO $1234 SLOi(ABS); break; //------------------------------------------------------------------------------------------- case 0x10: BPLInstrHandler(); break; case 0x11: ORAInstrHandler(IndYAddrModeHandler_Data()); break; case 0x12: STOPi(); break; case 0x13: // MHG SLO SLOi(INDY); break; case 0x14: // MHG NOP NOPi(ZPX); break; case 0x15: ORAInstrHandler(ZeroPgXAddrModeHandler_Data()); break; case 0x16: ASLInstrHandler(ZeroPgXAddrModeHandler_Address()); break; case 0x17: // MHG SLO SLOi(ZPX); break; case 0x18: PSR&=255-FlagC; /* CLC */ break; case 0x19: ORAInstrHandler(AbsYAddrModeHandler_Data()); break; case 0x1A: // MHG NOP NOPi(IMPLIED); break; case 0x1b: // MHG SLO SLOi(ABSY); break; case 0x1c: // MHG NOP NOPi(ABSX); break; case 0x1d: ORAInstrHandler(AbsXAddrModeHandler_Data()); break; case 0x1e: ASLInstrHandler(AbsXAddrModeHandler_Address()); break; case 0x1f: // MHG SLO SLOi(ABSX); break; //------------------------------------------------------------------------------------------- case 0x20: JSRInstrHandler(AbsAddrModeHandler_Address()); break; case 0x21: ANDInstrHandler(IndXAddrModeHandler_Data()); break; case 0x22: // MHG STOPi(); break; case 0x23: // MHG RLAi(INDX); break; case 0x24: BITInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0x25: ANDInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0x26: ROLInstrHandler(ZeroPgAddrModeHandler_Address()); break; case 0x27: RLAi(ZP); // MHG break; case 0x28: PSR=Pop(); /* PLP */ break; case 0x29: ANDInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0x2a: ROLInstrHandler_Acc(); break; case 0x2b: // MHG ANCi(IMMEDIATE); break; case 0x2c: BITInstrHandler(AbsAddrModeHandler_Data()); break; case 0x2d: ANDInstrHandler(AbsAddrModeHandler_Data()); break; case 0x2e: ROLInstrHandler(AbsAddrModeHandler_Address()); break; case 0x2f: // MHG RLAi(ABS); break; //------------------------------------------------------------------------------------------- case 0x30: BMIInstrHandler(); break; case 0x31: ANDInstrHandler(IndYAddrModeHandler_Data()); break; case 0x32: // MHG STOPi(); break; case 0x33: // MHG RLAi(INDY); break; case 0x34: // MHG NOPi(ZPX); break; case 0x35: ANDInstrHandler(ZeroPgXAddrModeHandler_Data()); break; case 0x36: ROLInstrHandler(ZeroPgXAddrModeHandler_Address()); break; case 0x37: // MHG RLAi(ZPX); break; case 0x38: PSR|=FlagC; /* SEC */ break; case 0x39: ANDInstrHandler(AbsYAddrModeHandler_Data()); break; case 0x3a: // MHG NOPi(IMPLIED); break; case 0x3b: // MHG RLAi(ABSY); break; case 0x3c: // MHG NOPi(ABSX); break; case 0x3d: ANDInstrHandler(AbsXAddrModeHandler_Data()); break; case 0x3e: ROLInstrHandler(AbsXAddrModeHandler_Address()); break; case 0x3f: ///MHG RLAi(ABSX); break; //------------------------------------------------------------------------------------------- case 0x40: PSR=Pop(); /* RTI */ ProgramCounter=PopWord(); NMILock=0; break; case 0x41: EORInstrHandler(IndXAddrModeHandler_Data()); break; case 0x42: // MHG STOPi(); break; case 0x43: // MHG SREi(INDX); break; case 0x44: // MHG NOPi(ZP); break; case 0x45: EORInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0x46: LSRInstrHandler(ZeroPgAddrModeHandler_Address()); break; case 0x47: // MHG SREi(ZP); break; case 0x48: Push(Accumulator); /* PHA */ break; case 0x49: EORInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0x4a: LSRInstrHandler_Acc(); break; case 0x4b: // MHG ASR A= (A & #imm) >> 1 ASRi(IMMEDIATE); break; case 0x4c: ProgramCounter=AbsAddrModeHandler_Address(); /* JMP */ break; case 0x4d: EORInstrHandler(AbsAddrModeHandler_Data()); break; case 0x4e: LSRInstrHandler(AbsAddrModeHandler_Address()); break; case 0x4f: // MHG SREi(ABS); break; //------------------------------------------------------------------------------------------- case 0x50: BVCInstrHandler(); break; case 0x51: EORInstrHandler(IndYAddrModeHandler_Data()); break; case 0x52: // MHG STOPi(); break; case 0x53: // MHG SREi(INDY); break; case 0x54: // MHG NOPi(ZPX); break; case 0x55: EORInstrHandler(ZeroPgXAddrModeHandler_Data()); break; case 0x56: LSRInstrHandler(ZeroPgXAddrModeHandler_Address()); break; case 0x57: // MHG SREi(ZPX); break; case 0x58: PSR&=255-FlagI; /* CLI */ break; case 0x59: EORInstrHandler(AbsYAddrModeHandler_Data()); break; case 0x5a: // MHG NOPi(IMPLIED); break; case 0x5b: // MHG SREi(ABSY); break; case 0x5c: // MHG NOPi(ABSX); break; case 0x5d: EORInstrHandler(AbsXAddrModeHandler_Data()); break; case 0x5e: LSRInstrHandler(AbsXAddrModeHandler_Address()); break; case 0x5f: // MHG SREi(ABSX); break; //------------------------------------------------------------------------------------------- case 0x60: ProgramCounter=PopWord()+1; /* RTS */ break; case 0x61: ADCInstrHandler(IndXAddrModeHandler_Data()); break; case 0x62: // MHG STOPi(); break; case 0x63: // MHG RRAi(INDX); break; case 0x64: // MHG NOPi(ZPX); break; case 0x65: ADCInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0x66: RORInstrHandler(ZeroPgAddrModeHandler_Address()); break; case 0x67: // MHG RRAi(ZP); break; case 0x68: Accumulator=Pop(); /* PLA */ PSR&=~(FlagZ | FlagN); PSR|=((Accumulator==0)<<1) | (Accumulator & 128); break; case 0x69: ADCInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0x6a: RORInstrHandler_Acc(); break; case 0x6b: ARRi(IMMEDIATE); break; case 0x6c: ProgramCounter=IndAddrModeHandler_Address(); /* JMP */ break; case 0x6d: ADCInstrHandler(AbsAddrModeHandler_Data()); break; case 0x6e: RORInstrHandler(AbsAddrModeHandler_Address()); break; case 0x6f: // MHG RRAi(ABS); break; //------------------------------------------------------------------------------------------- case 0x70: BVSInstrHandler(); break; case 0x71: ADCInstrHandler(IndYAddrModeHandler_Data()); break; case 0x72: // MHG STOPi(); break; case 0x73: // MHG RRAi(INDY); break; case 0x74: // MHG NOPi(ZPX); break; case 0x75: ADCInstrHandler(ZeroPgXAddrModeHandler_Data()); break; case 0x76: RORInstrHandler(ZeroPgXAddrModeHandler_Address()); break; case 0x77: // MHG RRAi(ZPX); break; case 0x78: PSR|=FlagI; /* SEI */ break; case 0x79: ADCInstrHandler(AbsYAddrModeHandler_Data()); break; case 0x7a: NOPi(IMPLIED); break; case 0x7b: RRAi(ABSY); break; case 0x7c: NOPi(ABSX); break; case 0x7d: ADCInstrHandler(AbsXAddrModeHandler_Data()); break; case 0x7e: RORInstrHandler(AbsXAddrModeHandler_Address()); break; case 0x7f: // MHG RRAi(ABSX); break; //------------------------------------------------------------------------------------------- case 0x80: // MHG NOPi(IMMEDIATE); break; case 0x81: FASTWRITE(IndXAddrModeHandler_Address(),Accumulator); /* STA */ break; case 0x82: // MHG NOPSi(IMMEDIATE); break; case 0x83: // MHG SAXi(INDX); break; case 0x84: BEEBWRITEMEM_DIRECT(ZeroPgAddrModeHandler_Address(),YReg); break; case 0x85: BEEBWRITEMEM_DIRECT(ZeroPgAddrModeHandler_Address(),Accumulator); /* STA */ break; case 0x86: BEEBWRITEMEM_DIRECT(ZeroPgAddrModeHandler_Address(),XReg); break; case 0x87: //MHG SAX stote (a and x) SAXi(ZP); break; case 0x88: YReg=(YReg-1) & 255; /* DEY */ PSR&=~(FlagZ | FlagN); PSR|=((YReg==0)<<1) | (YReg & 128); break; case 0x89: NOPi(IMMEDIATE); break; case 0x8a: Accumulator=XReg; /* TXA */ PSR&=~(FlagZ | FlagN); PSR|=((Accumulator==0)<<1) | (Accumulator & 128); break; case 0x8b: // MHG ANEi(IMMEDIATE); break; case 0x8c: STYInstrHandler(AbsAddrModeHandler_Address()); break; case 0x8d: FASTWRITE(AbsAddrModeHandler_Address(),Accumulator); /* STA */ break; case 0x8e: STXInstrHandler(AbsAddrModeHandler_Address()); break; case 0x8f: // MHG SAXi(ABS); break; //------------------------------------------------------------------------------------------- case 0x90: BCCInstrHandler(); break; case 0x91: FASTWRITE(IndYAddrModeHandler_Address(),Accumulator); /* STA */ break; case 0x92: // MHG STOPi(); break; case 0x93: // MHG SHAi(INDY); break; case 0x94: STYInstrHandler(ZeroPgXAddrModeHandler_Address()); break; case 0x95: FASTWRITE(ZeroPgXAddrModeHandler_Address(),Accumulator); /* STA */ break; case 0x96: STXInstrHandler(ZeroPgYAddrModeHandler_Address()); break; case 0x97: // MHG SAXi(ZPY); break; case 0x98: Accumulator=YReg; /* TYA */ PSR&=~(FlagZ | FlagN); PSR|=((Accumulator==0)<<1) | (Accumulator & 128); break; case 0x99: FASTWRITE(AbsYAddrModeHandler_Address(),Accumulator); /* STA */ break; case 0x9a: StackReg=XReg; /* TXS */ break; case 0x9b: // MHG SHSi(); break; case 0x9c: // MHG SHYi(ABSX); break; case 0x9d: FASTWRITE(AbsXAddrModeHandler_Address(),Accumulator); /* STA */ break; case 0x9e: // MHG SHXi(ABSY); break; case 0x9f: // MHG SHAi(ABSY); break; //------------------------------------------------------------------------------------------- case 0xa0: LDYInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0xa1: LDAInstrHandler(IndXAddrModeHandler_Data()); break; case 0xa2: LDXInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0xa3: // MHG LAXi(INDX); break; case 0xa4: LDYInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0xa5: LDAInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0xa6: LDXInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0xa7: // MHG LAXi(ZP); break; case 0xa8: YReg=Accumulator; /* TAY */ PSR&=~(FlagZ | FlagN); PSR|=((Accumulator==0)<<1) | (Accumulator & 128); break; case 0xa9: LDAInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0xaa: XReg=Accumulator; /* TXA */ PSR&=~(FlagZ | FlagN); PSR|=((Accumulator==0)<<1) | (Accumulator & 128); break; case 0xab: // MHG LXAi(IMMEDIATE); break; case 0xac: LDYInstrHandler(AbsAddrModeHandler_Data()); break; case 0xad: LDAInstrHandler(AbsAddrModeHandler_Data()); break; case 0xae: LDXInstrHandler(AbsAddrModeHandler_Data()); break; case 0xaf: // MHG LAXi(ABS); break; //------------------------------------------------------------------------------------------- case 0xb0: BCSInstrHandler(); break; case 0xb1: LDAInstrHandler(IndYAddrModeHandler_Data()); break; case 0xb2: // MHG STOPi(); break; case 0xb3: // MHG LAXi(INDY); break; case 0xb4: LDYInstrHandler(ZeroPgXAddrModeHandler_Data()); break; case 0xb5: LDAInstrHandler(ZeroPgXAddrModeHandler_Data()); break; case 0xb6: LDXInstrHandler(ZeroPgYAddrModeHandler_Data()); break; case 0xb7: // MHG LAXi(ZPY); break; case 0xb8: PSR&=255-FlagV; /* CLV */ break; case 0xb9: LDAInstrHandler(AbsYAddrModeHandler_Data()); break; case 0xba: XReg=StackReg; /* TSX */ PSR&=~(FlagZ | FlagN); PSR|=((XReg==0)<<1) | (XReg & 128); break; case 0xbb: LASi(ABSY); break; case 0xbc: LDYInstrHandler(AbsXAddrModeHandler_Data()); break; case 0xbd: LDAInstrHandler(AbsXAddrModeHandler_Data()); break; case 0xbe: LDXInstrHandler(AbsYAddrModeHandler_Data()); break; case 0xbf: // MHG LAXi(ABSY); break; //------------------------------------------------------------------------------------------- case 0xc0: CPYInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0xc1: CMPInstrHandler(IndXAddrModeHandler_Data()); break; case 0xc2: // MHG NOPSi(IMMEDIATE); break; case 0xc3: // MHG DCPi(INDX); break; case 0xc4: CPYInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0xc5: CMPInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0xc6: DECInstrHandler(ZeroPgAddrModeHandler_Address()); break; case 0xc7: // MHG DCPi(ZP); break; case 0xc8: YReg+=1; /* INY */ YReg&=255; PSR&=~(FlagZ | FlagN); PSR|=((YReg==0)<<1) | (YReg & 128); break; case 0xc9: CMPInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0xca: DEXInstrHandler(); break; case 0xcb: // MHG SBXi(IMMEDIATE); break; case 0xcc: CPYInstrHandler(AbsAddrModeHandler_Data()); break; case 0xcd: CMPInstrHandler(AbsAddrModeHandler_Data()); break; case 0xce: DECInstrHandler(AbsAddrModeHandler_Address()); break; case 0xcf: // MHG DCPi(ABS); break; //------------------------------------------------------------------------------------------- case 0xd0: BNEInstrHandler(); break; case 0xd1: CMPInstrHandler(IndYAddrModeHandler_Data()); break; case 0xd2: // MHG STOPi(); break; case 0xd3: // MHG DCPi(INDY); break; case 0xd4: // MHG NOPi(ZPX); break; case 0xd5: CMPInstrHandler(ZeroPgXAddrModeHandler_Data()); break; case 0xd6: DECInstrHandler(ZeroPgXAddrModeHandler_Address()); break; case 0xd7: // MHG DCPi(ZPY); break; case 0xd8: PSR&=255-FlagD; /* CLD */ break; case 0xd9: CMPInstrHandler(AbsYAddrModeHandler_Data()); break; case 0xda: // MHG NOPi(IMPLIED); break; case 0xdb: // MHG DCPi(ABSY); break; case 0xDC: // MHG NOPi(ABSX); break; case 0xdd: CMPInstrHandler(AbsXAddrModeHandler_Data()); break; case 0xde: DECInstrHandler(AbsXAddrModeHandler_Address()); break; case 0xdf: // MHG DCPi(ABSX); break; //------------------------------------------------------------------------------------------- case 0xe0: CPXInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0xe1: SBCInstrHandler(IndXAddrModeHandler_Data()); break; case 0xe2: // MHG NOPSi(IMMEDIATE); break; case 0xe3: // MHG ISBi(INDX); break; case 0xe4: CPXInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0xe5: SBCInstrHandler(WholeRam[WholeRam[ProgramCounter++]]/*zp */); break; case 0xe6: INCInstrHandler(ZeroPgAddrModeHandler_Address()); break; case 0xe7: // MHG ISBi(ZP); break; case 0xe8: INXInstrHandler(); break; case 0xe9: SBCInstrHandler(WholeRam[ProgramCounter++]); /* immediate */ break; case 0xea: // MHG break; case 0xeb: // MHG SBCi(IMMEDIATE); break; case 0xec: CPXInstrHandler(AbsAddrModeHandler_Data()); break; case 0xed: SBCInstrHandler(AbsAddrModeHandler_Data()); break; case 0xee: INCInstrHandler(AbsAddrModeHandler_Address()); break; case 0xef: // MHG ISBi(ABS); break; //------------------------------------------------------------------------------------------- case 0xf0: BEQInstrHandler(); break; case 0xf1: SBCInstrHandler(IndYAddrModeHandler_Data()); break; case 0xf2: // MHG STOPi(); break; case 0xf3: // MHG ISBi(INDY); break; case 0xf4: // MHG NOPi(ZPX); break; case 0xf5: SBCInstrHandler(ZeroPgXAddrModeHandler_Data()); break; case 0xf6: INCInstrHandler(ZeroPgXAddrModeHandler_Address()); break; case 0xf7: // MHG ISBi(ZPX); break; case 0xf8: PSR|=FlagD; /* SED */ break; case 0xf9: SBCInstrHandler(AbsYAddrModeHandler_Data()); break; case 0xfa: // MHG NOPi(IMPLIED); break; case 0xfb: // MHG ISBi(ABSY); break; case 0xFC: // MHG NOPi(ABSX); break; case 0xfd: SBCInstrHandler(AbsXAddrModeHandler_Data()); break; case 0xfe: INCInstrHandler(AbsXAddrModeHandler_Address()); break; case 0xff: // MHG ISBi(ABSX); break; //------------------------------------------------------------------------------------------- default: BadInstrHandler(CurrentInstruction); break; }; /* OpCode switch */ OldNMIStatus=NMIStatus; /* NOTE: Check IRQ status before polling hardware - this is essential for Rocket Raid to work since it polls the IFR in the sys via for start of frame - but with interrupts enabled. If you do the interrupt check later then the interrupt handler will always be entered and rocket raid will never see it */ if ((intStatus) && (!GETIFLAG)) DoInterrupt(); TotalCycles+=Cycles; VideoPoll(Cycles); SysVIA_poll(Cycles); UserVIA_poll(Cycles); Disc8271_poll(Cycles); Sound_Trigger(Cycles); ///THIS IT IT if ((NMIStatus) && (!OldNMIStatus)) DoNMI(); }; } /* Exec6502Instruction */ /*-------------------------------------------------------------------------*/ /* Dump state */ void core_dumpstate(void) { cerr << "core:\n"; DumpRegs(); }; /* core_dumpstate */ char bad[]= { 0x02, 0x03, 0x04, 0x07, 0x0b, 0x0c, 0x0f, 0x12, 0x13, 0x14, 0x17, 0x1a, 0x1b, 0x1c, 0x1f, 0x22, 0x23, 0x27, 0x2b, 0x2f, 0x32, 0x33, 0x34, 0x37, 0x3a, 0x3b, 0x3c, 0x3f, 0x42, 0x43, 0x44, 0x47, 0x4b, 0x4f, 0x52, 0x53, 0x54, 0x57, 0x5a, 0x5b, 0x5c, 0x5f, 0x62, 0x63, 0x64, 0x67, 0x6b, 0x6f, 0x72, 0x73, 0x74, 0x77, 0x7a, 0x7b, 0x7c, 0x7f, 0x80, 0x82, 0x83, 0x87, 0x8b, 0x8f, 0x92, 0x93, 0x97, 0x9b, 0x9c, 0x9e, 0x9f, 0xa3, 0xa7, 0xab, 0xaf, 0xb2, 0xb3, 0xb7, 0xbb, 0xbf, 0xc2, 0xc3, 0xc7, 0xcb, 0xcf, 0xd2, 0xd3, 0xd4, 0xd7, 0xda, 0xdb, 0xdc, 0xdf, 0xe2, 0xe3, 0xe7, 0xeb, 0xef, 0xf2, 0xf3, 0xf4, 0xf7, 0xfa, 0xfb, 0xfc, 0xff }; void check_op(int a) { int i=0; while(1) { if (bad[i]==a) printf("op 0x%x %d\n",a,a); i++; if (i>=256) break; if (bad[i]==255) break; } }