Remove Marat Fayzullin 6502 emulation code
This commit is contained in:
parent
12663ba99a
commit
e96f36b6de
@ -1,838 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** Codes.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the main table of **/
|
||||
/** 6502 commands. It is included from 6502.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** Alex Krasivsky 1996 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate$
|
||||
* $Author$
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
case 0x10:
|
||||
if (R->P & N_FLAG)
|
||||
R->PC.W++;
|
||||
else
|
||||
{
|
||||
M_JR;
|
||||
} break; /* BPL * REL */
|
||||
|
||||
case 0x30:
|
||||
if (R->P & N_FLAG)
|
||||
{
|
||||
M_JR;
|
||||
}
|
||||
else
|
||||
R->PC.W++;
|
||||
break; /* BMI * REL */
|
||||
|
||||
case 0xD0:
|
||||
if (R->P & Z_FLAG)
|
||||
R->PC.W++;
|
||||
else
|
||||
{
|
||||
M_JR;
|
||||
} break; /* BNE * REL */
|
||||
|
||||
case 0xF0:
|
||||
if (R->P & Z_FLAG)
|
||||
{
|
||||
M_JR;
|
||||
}
|
||||
else
|
||||
R->PC.W++;
|
||||
break; /* BEQ * REL */
|
||||
|
||||
case 0x90:
|
||||
if (R->P & C_FLAG)
|
||||
R->PC.W++;
|
||||
else
|
||||
{
|
||||
M_JR;
|
||||
} break; /* BCC * REL */
|
||||
|
||||
case 0xB0:
|
||||
if (R->P & C_FLAG)
|
||||
{
|
||||
M_JR;
|
||||
}
|
||||
else
|
||||
R->PC.W++;
|
||||
break; /* BCS * REL */
|
||||
|
||||
case 0x50:
|
||||
if (R->P & V_FLAG)
|
||||
R->PC.W++;
|
||||
else
|
||||
{
|
||||
M_JR;
|
||||
} break; /* BVC * REL */
|
||||
|
||||
case 0x70:
|
||||
if (R->P & V_FLAG)
|
||||
{
|
||||
M_JR;
|
||||
}
|
||||
else
|
||||
R->PC.W++;
|
||||
break; /* BVS * REL */
|
||||
|
||||
|
||||
/* RTI */
|
||||
case 0x40:
|
||||
|
||||
M_POP(R->P);
|
||||
//R->P |= R_FLAG;
|
||||
M_POP(R->PC.B.l);
|
||||
M_POP(R->PC.B.h);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* RTS */
|
||||
case 0x60:
|
||||
|
||||
M_POP(R->PC.B.l);
|
||||
M_POP(R->PC.B.h);
|
||||
R->PC.W++;
|
||||
break;
|
||||
|
||||
|
||||
/* JSR $ssss ABS */
|
||||
case 0x20:
|
||||
|
||||
K.B.l = Op6502(R->PC.W++);
|
||||
|
||||
K.B.h = Op6502(R->PC.W);
|
||||
|
||||
M_PUSH(R->PC.B.h);
|
||||
|
||||
M_PUSH(R->PC.B.l);
|
||||
|
||||
R->PC = K;
|
||||
break;
|
||||
|
||||
|
||||
/* JMP $ssss ABS */
|
||||
case 0x4C:
|
||||
M_LDWORD(K);
|
||||
R->PC = K;
|
||||
break;
|
||||
|
||||
|
||||
/* JMP ($ssss) ABDINDIR */
|
||||
case 0x6C:
|
||||
|
||||
M_LDWORD(K);
|
||||
|
||||
R->PC.B.l = Rd6502(K.W);
|
||||
|
||||
K.B.l++;
|
||||
|
||||
R->PC.B.h = Rd6502(K.W);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* BRK */
|
||||
case 0x00:
|
||||
|
||||
R->PC.W++;
|
||||
|
||||
M_PUSH(R->PC.B.h);
|
||||
M_PUSH(R->PC.B.l);
|
||||
|
||||
M_PUSH(R->P | B_FLAG);
|
||||
|
||||
R->P = (R->P | I_FLAG) & ~D_FLAG;
|
||||
|
||||
R->PC.B.l = Rd6502(0xFFFE);
|
||||
|
||||
R->PC.B.h = Rd6502(0xFFFF);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* CLI */
|
||||
case 0x58:
|
||||
|
||||
if ((R->IRequest != INT_NONE) && (R->P & I_FLAG))
|
||||
|
||||
{
|
||||
|
||||
R->AfterCLI = 1;
|
||||
|
||||
R->IBackup = R->ICount;
|
||||
|
||||
R->ICount = 1;
|
||||
|
||||
}
|
||||
R->P &= ~I_FLAG;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* PLP */
|
||||
case 0x28:
|
||||
|
||||
M_POP(I);
|
||||
|
||||
if ((R->IRequest != INT_NONE) && ((I ^ R->P) & ~I & I_FLAG))
|
||||
|
||||
{
|
||||
|
||||
R->AfterCLI = 1;
|
||||
|
||||
R->IBackup = R->ICount;
|
||||
|
||||
R->ICount = 1;
|
||||
|
||||
}
|
||||
R->P = I /*| R_FLAG*/ | B_FLAG;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 0x08:
|
||||
M_PUSH(R->P);
|
||||
break; /* PHP */
|
||||
|
||||
case 0x18:
|
||||
R->P &= ~C_FLAG;
|
||||
break; /* CLC */
|
||||
|
||||
case 0xB8:
|
||||
R->P &= ~V_FLAG;
|
||||
break; /* CLV */
|
||||
|
||||
case 0xD8:
|
||||
R->P &= ~D_FLAG;
|
||||
break; /* CLD */
|
||||
|
||||
case 0x38:
|
||||
R->P |= C_FLAG;
|
||||
break; /* SEC */
|
||||
|
||||
case 0xF8:
|
||||
R->P |= D_FLAG;
|
||||
break; /* SED */
|
||||
|
||||
case 0x78:
|
||||
R->P |= I_FLAG;
|
||||
break; /* SEI */
|
||||
|
||||
case 0x48:
|
||||
M_PUSH(R->A);
|
||||
break; /* PHA */
|
||||
|
||||
case 0x68:
|
||||
M_POP(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* PLA */
|
||||
|
||||
case 0x98:
|
||||
R->A = R->Y;
|
||||
M_FL(R->A);
|
||||
break; /* TYA */
|
||||
|
||||
case 0xA8:
|
||||
R->Y = R->A;
|
||||
M_FL(R->Y);
|
||||
break; /* TAY */
|
||||
|
||||
case 0xC8:
|
||||
R->Y++;
|
||||
M_FL(R->Y);
|
||||
break; /* INY */
|
||||
|
||||
case 0x88:
|
||||
R->Y--;
|
||||
M_FL(R->Y);
|
||||
break; /* DEY */
|
||||
|
||||
case 0x8A:
|
||||
R->A = R->X;
|
||||
M_FL(R->A);
|
||||
break; /* TXA */
|
||||
|
||||
case 0xAA:
|
||||
R->X = R->A;
|
||||
M_FL(R->X);
|
||||
break; /* TAX */
|
||||
|
||||
case 0xE8:
|
||||
R->X++;
|
||||
M_FL(R->X);
|
||||
break; /* INX */
|
||||
|
||||
case 0xCA:
|
||||
R->X--;
|
||||
M_FL(R->X);
|
||||
break; /* DEX */
|
||||
|
||||
default: /* In CMOS version unrecognized instructions are concidered as
|
||||
NOP */
|
||||
case 0xEA:
|
||||
break; /* NOP */
|
||||
|
||||
case 0x9A:
|
||||
R->S = R->X;
|
||||
break; /* TXS */
|
||||
|
||||
case 0xBA:
|
||||
R->X = R->S;
|
||||
M_FL(R->X);
|
||||
break; /* TSX */
|
||||
|
||||
|
||||
case 0x24:
|
||||
MR_Zp(I);
|
||||
M_BIT(I);
|
||||
break; /* BIT $ss ZP */
|
||||
|
||||
case 0x2C:
|
||||
MR_Ab(I);
|
||||
M_BIT(I);
|
||||
break; /* BIT $ssss ABS */
|
||||
|
||||
|
||||
case 0x05:
|
||||
MR_Zp(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ss ZP */
|
||||
|
||||
case 0x06:
|
||||
MM_Zp(M_ASL);
|
||||
break; /* ASL $ss ZP */
|
||||
|
||||
case 0x25:
|
||||
MR_Zp(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ss ZP */
|
||||
|
||||
case 0x26:
|
||||
MM_Zp(M_ROL);
|
||||
break; /* ROL $ss ZP */
|
||||
|
||||
case 0x45:
|
||||
MR_Zp(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ss ZP */
|
||||
|
||||
case 0x46:
|
||||
MM_Zp(M_LSR);
|
||||
break; /* LSR $ss ZP */
|
||||
|
||||
case 0x65:
|
||||
MR_Zp(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ss ZP */
|
||||
|
||||
case 0x66:
|
||||
MM_Zp(M_ROR);
|
||||
break; /* ROR $ss ZP */
|
||||
|
||||
case 0x84:
|
||||
MW_Zp(R->Y);
|
||||
break; /* STY $ss ZP */
|
||||
|
||||
case 0x85:
|
||||
MW_Zp(R->A);
|
||||
break; /* STA $ss ZP */
|
||||
|
||||
case 0x86:
|
||||
MW_Zp(R->X);
|
||||
break; /* STX $ss ZP */
|
||||
|
||||
case 0xA4:
|
||||
MR_Zp(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY $ss ZP */
|
||||
|
||||
case 0xA5:
|
||||
MR_Zp(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ss ZP */
|
||||
|
||||
case 0xA6:
|
||||
MR_Zp(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX $ss ZP */
|
||||
|
||||
case 0xC4:
|
||||
MR_Zp(I);
|
||||
M_CMP(R->Y, I);
|
||||
break; /* CPY $ss ZP */
|
||||
|
||||
case 0xC5:
|
||||
MR_Zp(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ss ZP */
|
||||
|
||||
case 0xC6:
|
||||
MM_Zp(M_DEC);
|
||||
break; /* DEC $ss ZP */
|
||||
|
||||
case 0xE4:
|
||||
MR_Zp(I);
|
||||
M_CMP(R->X, I);
|
||||
break; /* CPX $ss ZP */
|
||||
|
||||
case 0xE5:
|
||||
MR_Zp(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ss ZP */
|
||||
|
||||
case 0xE6:
|
||||
MM_Zp(M_INC);
|
||||
break; /* INC $ss ZP */
|
||||
|
||||
|
||||
case 0x0D:
|
||||
MR_Ab(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ssss ABS */
|
||||
|
||||
case 0x0E:
|
||||
MM_Ab(M_ASL);
|
||||
break; /* ASL $ssss ABS */
|
||||
|
||||
case 0x2D:
|
||||
MR_Ab(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ssss ABS */
|
||||
|
||||
case 0x2E:
|
||||
MM_Ab(M_ROL);
|
||||
break; /* ROL $ssss ABS */
|
||||
|
||||
case 0x4D:
|
||||
MR_Ab(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ssss ABS */
|
||||
|
||||
case 0x4E:
|
||||
MM_Ab(M_LSR);
|
||||
break; /* LSR $ssss ABS */
|
||||
|
||||
case 0x6D:
|
||||
MR_Ab(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ssss ABS */
|
||||
|
||||
case 0x6E:
|
||||
MM_Ab(M_ROR);
|
||||
break; /* ROR $ssss ABS */
|
||||
|
||||
case 0x8C:
|
||||
MW_Ab(R->Y);
|
||||
break; /* STY $ssss ABS */
|
||||
|
||||
case 0x8D:
|
||||
MW_Ab(R->A);
|
||||
break; /* STA $ssss ABS */
|
||||
|
||||
case 0x8E:
|
||||
MW_Ab(R->X);
|
||||
break; /* STX $ssss ABS */
|
||||
|
||||
case 0xAC:
|
||||
MR_Ab(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY $ssss ABS */
|
||||
|
||||
case 0xAD:
|
||||
MR_Ab(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ssss ABS */
|
||||
|
||||
case 0xAE:
|
||||
MR_Ab(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX $ssss ABS */
|
||||
|
||||
case 0xCC:
|
||||
MR_Ab(I);
|
||||
M_CMP(R->Y, I);
|
||||
break; /* CPY $ssss ABS */
|
||||
|
||||
case 0xCD:
|
||||
MR_Ab(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ssss ABS */
|
||||
|
||||
case 0xCE:
|
||||
MM_Ab(M_DEC);
|
||||
break; /* DEC $ssss ABS */
|
||||
|
||||
case 0xEC:
|
||||
MR_Ab(I);
|
||||
M_CMP(R->X, I);
|
||||
break; /* CPX $ssss ABS */
|
||||
|
||||
case 0xED:
|
||||
MR_Ab(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ssss ABS */
|
||||
|
||||
case 0xEE:
|
||||
MM_Ab(M_INC);
|
||||
break; /* INC $ssss ABS */
|
||||
|
||||
|
||||
case 0x09:
|
||||
MR_Im(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA #$ss IMM */
|
||||
|
||||
case 0x29:
|
||||
MR_Im(I);
|
||||
M_AND(I);
|
||||
break; /* AND #$ss IMM */
|
||||
|
||||
case 0x49:
|
||||
MR_Im(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR #$ss IMM */
|
||||
|
||||
case 0x69:
|
||||
MR_Im(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC #$ss IMM */
|
||||
|
||||
case 0xA0:
|
||||
MR_Im(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY #$ss IMM */
|
||||
|
||||
case 0xA2:
|
||||
MR_Im(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX #$ss IMM */
|
||||
|
||||
case 0xA9:
|
||||
MR_Im(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA #$ss IMM */
|
||||
|
||||
case 0xC0:
|
||||
MR_Im(I);
|
||||
M_CMP(R->Y, I);
|
||||
break; /* CPY #$ss IMM */
|
||||
|
||||
case 0xC9:
|
||||
MR_Im(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP #$ss IMM */
|
||||
|
||||
case 0xE0:
|
||||
MR_Im(I);
|
||||
M_CMP(R->X, I);
|
||||
break; /* CPX #$ss IMM */
|
||||
|
||||
case 0xE9:
|
||||
MR_Im(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC #$ss IMM */
|
||||
|
||||
|
||||
case 0x15:
|
||||
MR_Zx(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ss,x ZP,x */
|
||||
|
||||
case 0x16:
|
||||
MM_Zx(M_ASL);
|
||||
break; /* ASL $ss,x ZP,x */
|
||||
|
||||
case 0x35:
|
||||
MR_Zx(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ss,x ZP,x */
|
||||
|
||||
case 0x36:
|
||||
MM_Zx(M_ROL);
|
||||
break; /* ROL $ss,x ZP,x */
|
||||
|
||||
case 0x55:
|
||||
MR_Zx(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ss,x ZP,x */
|
||||
|
||||
case 0x56:
|
||||
MM_Zx(M_LSR);
|
||||
break; /* LSR $ss,x ZP,x */
|
||||
|
||||
case 0x75:
|
||||
MR_Zx(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ss,x ZP,x */
|
||||
|
||||
case 0x76:
|
||||
MM_Zx(M_ROR);
|
||||
break; /* ROR $ss,x ZP,x */
|
||||
|
||||
case 0x94:
|
||||
MW_Zx(R->Y);
|
||||
break; /* STY $ss,x ZP,x */
|
||||
|
||||
case 0x95:
|
||||
MW_Zx(R->A);
|
||||
break; /* STA $ss,x ZP,x */
|
||||
|
||||
case 0x96:
|
||||
MW_Zy(R->X);
|
||||
break; /* STX $ss,y ZP,y */
|
||||
|
||||
case 0xB4:
|
||||
MR_Zx(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY $ss,x ZP,x */
|
||||
|
||||
case 0xB5:
|
||||
MR_Zx(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ss,x ZP,x */
|
||||
|
||||
case 0xB6:
|
||||
MR_Zy(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX $ss,y ZP,y */
|
||||
|
||||
case 0xD5:
|
||||
MR_Zx(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ss,x ZP,x */
|
||||
|
||||
case 0xD6:
|
||||
MM_Zx(M_DEC);
|
||||
break; /* DEC $ss,x ZP,x */
|
||||
|
||||
case 0xF5:
|
||||
MR_Zx(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ss,x ZP,x */
|
||||
|
||||
case 0xF6:
|
||||
MM_Zx(M_INC);
|
||||
break; /* INC $ss,x ZP,x */
|
||||
|
||||
|
||||
case 0x19:
|
||||
MR_Ay(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ssss,y ABS,y */
|
||||
|
||||
case 0x1D:
|
||||
MR_Ax(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ssss,x ABS,x */
|
||||
|
||||
case 0x1E:
|
||||
MM_Ax(M_ASL);
|
||||
break; /* ASL $ssss,x ABS,x */
|
||||
|
||||
case 0x39:
|
||||
MR_Ay(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ssss,y ABS,y */
|
||||
|
||||
case 0x3D:
|
||||
MR_Ax(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ssss,x ABS,x */
|
||||
|
||||
case 0x3E:
|
||||
MM_Ax(M_ROL);
|
||||
break; /* ROL $ssss,x ABS,x */
|
||||
|
||||
case 0x59:
|
||||
MR_Ay(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ssss,y ABS,y */
|
||||
|
||||
case 0x5D:
|
||||
MR_Ax(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ssss,x ABS,x */
|
||||
|
||||
case 0x5E:
|
||||
MM_Ax(M_LSR);
|
||||
break; /* LSR $ssss,x ABS,x */
|
||||
|
||||
case 0x79:
|
||||
MR_Ay(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ssss,y ABS,y */
|
||||
|
||||
case 0x7D:
|
||||
MR_Ax(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ssss,x ABS,x */
|
||||
|
||||
case 0x7E:
|
||||
MM_Ax(M_ROR);
|
||||
break; /* ROR $ssss,x ABS,x */
|
||||
|
||||
case 0x99:
|
||||
MW_Ay(R->A);
|
||||
break; /* STA $ssss,y ABS,y */
|
||||
|
||||
case 0x9D:
|
||||
MW_Ax(R->A);
|
||||
break; /* STA $ssss,x ABS,x */
|
||||
|
||||
case 0xB9:
|
||||
MR_Ay(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ssss,y ABS,y */
|
||||
|
||||
case 0xBC:
|
||||
MR_Ax(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY $ssss,x ABS,x */
|
||||
|
||||
case 0xBD:
|
||||
MR_Ax(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ssss,x ABS,x */
|
||||
|
||||
case 0xBE:
|
||||
MR_Ay(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX $ssss,y ABS,y */
|
||||
|
||||
case 0xD9:
|
||||
MR_Ay(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ssss,y ABS,y */
|
||||
|
||||
case 0xDD:
|
||||
MR_Ax(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ssss,x ABS,x */
|
||||
|
||||
case 0xDE:
|
||||
MM_Ax(M_DEC);
|
||||
break; /* DEC $ssss,x ABS,x */
|
||||
|
||||
case 0xF9:
|
||||
MR_Ay(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ssss,y ABS,y */
|
||||
|
||||
case 0xFD:
|
||||
MR_Ax(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ssss,x ABS,x */
|
||||
|
||||
case 0xFE:
|
||||
MM_Ax(M_INC);
|
||||
break; /* INC $ssss,x ABS,x */
|
||||
|
||||
|
||||
case 0x01:
|
||||
MR_Ix(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x11:
|
||||
MR_Iy(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA ($ss),y INDIRINDEX */
|
||||
|
||||
case 0x21:
|
||||
MR_Ix(I);
|
||||
M_AND(I);
|
||||
break; /* AND ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x31:
|
||||
MR_Iy(I);
|
||||
M_AND(I);
|
||||
break; /* AND ($ss),y INDIRINDEX */
|
||||
|
||||
case 0x41:
|
||||
MR_Ix(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x51:
|
||||
MR_Iy(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR ($ss),y INDIRINDEX */
|
||||
|
||||
case 0x61:
|
||||
MR_Ix(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x71:
|
||||
MR_Iy(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC ($ss),y INDIRINDEX */
|
||||
|
||||
case 0x81:
|
||||
MW_Ix(R->A);
|
||||
break; /* STA ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x91:
|
||||
MW_Iy(R->A);
|
||||
break; /* STA ($ss),y INDIRINDEX */
|
||||
|
||||
case 0xA1:
|
||||
MR_Ix(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0xB1:
|
||||
MR_Iy(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA ($ss),y INDIRINDEX */
|
||||
|
||||
case 0xC1:
|
||||
MR_Ix(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0xD1:
|
||||
MR_Iy(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP ($ss),y INDIRINDEX */
|
||||
|
||||
case 0xE1:
|
||||
MR_Ix(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0xF1:
|
||||
MR_Iy(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC ($ss),y INDIRINDEX */
|
||||
|
||||
|
||||
case 0x0A:
|
||||
M_ASL(R->A);
|
||||
break; /* ASL a ACC */
|
||||
|
||||
case 0x2A:
|
||||
M_ROL(R->A);
|
||||
break; /* ROL a ACC */
|
||||
|
||||
case 0x4A:
|
||||
M_LSR(R->A);
|
||||
break; /* LSR a ACC */
|
||||
|
||||
case 0x6A:
|
||||
M_ROR(R->A);
|
||||
break; /* ROR a ACC */
|
||||
|
||||
|
||||
@ -1,482 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** Debug.c **/
|
||||
/** **/
|
||||
/** This file contains the built-in debugging routine for **/
|
||||
/** the 6502 emulator which is called on each 6502 step **/
|
||||
/** when Trap!=0. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-1997 **/
|
||||
/** Alex Krasivsky 1996 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate$
|
||||
* $Author$
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include "M6502.h"
|
||||
#ifdef DEBUG
|
||||
#include <allegro.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <ppu/ppu.h>
|
||||
|
||||
#include <mappers/manager.h>
|
||||
#include <memory/manager.h>
|
||||
#include <Sound.h>
|
||||
|
||||
#define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
|
||||
|
||||
extern unsigned char *Memory;
|
||||
|
||||
void showlastop();
|
||||
|
||||
enum Addressing_Modes
|
||||
{
|
||||
Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
|
||||
};
|
||||
|
||||
|
||||
|
||||
static char *mn[] =
|
||||
{
|
||||
"adc ", "and ", "asl ", "bcc ", "bcs ", "beq ", "bit ", "bmi ",
|
||||
"bne ", "bpl ", "brk", "bvc ", "bvs ", "clc", "cld", "cli",
|
||||
"clv", "cmp ", "cpx ", "cpy ", "dec ", "dex", "dey", "inx",
|
||||
"iny", "eor ", "inc ", "jmp ", "jsr ", "lda ", "nop ", "ldx ",
|
||||
"ldy ", "lsr ", "ora ", "pha", "php", "pla", "plp", "rol ",
|
||||
"ror ", "rti", "rts", "sbc ", "sta ", "stx ", "sty ", "sec ",
|
||||
"sed", "sei", "tax", "tay", "txa", "tya", "tsx", "txs"
|
||||
};
|
||||
|
||||
|
||||
|
||||
static byte ad[512] =
|
||||
{
|
||||
10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
|
||||
36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
|
||||
9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
|
||||
13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
|
||||
28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
|
||||
38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
|
||||
7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
|
||||
47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
|
||||
41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
|
||||
35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
|
||||
11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
|
||||
15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
|
||||
42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
|
||||
37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
|
||||
12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
|
||||
49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
|
||||
No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
|
||||
22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
|
||||
3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
|
||||
53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
|
||||
32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
|
||||
51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
|
||||
4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
|
||||
16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
|
||||
19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
|
||||
24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
|
||||
8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
|
||||
14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
|
||||
18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
|
||||
23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
|
||||
5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
|
||||
48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** DAsm() ****************************************************/
|
||||
/** This function will disassemble a single command and **/
|
||||
/** return the number of bytes disassembled. **/
|
||||
/**************************************************************/
|
||||
int DAsm(char *S, word A)
|
||||
{
|
||||
|
||||
byte J;
|
||||
|
||||
word B, OP, TO;
|
||||
|
||||
|
||||
B = A;
|
||||
OP = Rd6502(B++) * 2;
|
||||
|
||||
|
||||
switch (ad[OP + 1])
|
||||
|
||||
{
|
||||
|
||||
case Ac:
|
||||
sprintf(S, "%s a", mn[ad[OP]]);
|
||||
break;
|
||||
|
||||
case Il:
|
||||
sprintf(S, "%s", mn[ad[OP]]);
|
||||
break;
|
||||
|
||||
|
||||
case Rl:
|
||||
J = Rd6502(B++);
|
||||
TO = A + 2 + ((J < 0x80) ? J : (J - 256));
|
||||
|
||||
sprintf(S, "%s $%04X", mn[ad[OP]], TO);
|
||||
break;
|
||||
|
||||
|
||||
case Im:
|
||||
sprintf(S, "%s #$%02X", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zp:
|
||||
sprintf(S, "%s $%02X", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zx:
|
||||
sprintf(S, "%s $%02X,x", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zy:
|
||||
sprintf(S, "%s $%02X,y", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Ix:
|
||||
sprintf(S, "%s ($%02X,x)", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Iy:
|
||||
sprintf(S, "%s ($%02X),y", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
|
||||
case Ab:
|
||||
sprintf(S, "%s $%04X", mn[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case Ax:
|
||||
sprintf(S, "%s $%04X,x", mn[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case Ay:
|
||||
sprintf(S, "%s $%04X,y", mn[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case In:
|
||||
sprintf(S, "%s ($%04X)", mn[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
sprintf(S, ".db $%02X; <Invalid OPcode>", OP / 2);
|
||||
|
||||
}
|
||||
return (B - A);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Debug6502() **********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the 6502 registers. Emulation exits **/
|
||||
/** if Debug6502() returns 0. **/
|
||||
/*************************************************************/
|
||||
byte Debug6502(M6502 * R)
|
||||
{
|
||||
static char FA[8] = "NVRBDIZC";
|
||||
char S[128];
|
||||
byte F;
|
||||
int J, I;
|
||||
|
||||
DAsm(S, R->PC.W);
|
||||
|
||||
printf
|
||||
(
|
||||
"A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
|
||||
R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
|
||||
);
|
||||
|
||||
|
||||
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
|
||||
|
||||
printf("%c", F & 0x80 ? FA[J] : '.');
|
||||
|
||||
puts("]");
|
||||
|
||||
|
||||
printf
|
||||
(
|
||||
"AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
|
||||
Rd6502(R->PC.W), S,
|
||||
Rd6502(0x0100 + (byte) (R->S + 1)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 2)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 3))
|
||||
);
|
||||
|
||||
|
||||
S[0] = 0;
|
||||
remove_keyboard();
|
||||
|
||||
#ifdef USE_SOUND
|
||||
StopSound();
|
||||
#endif
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
printf("\n[Command,'?']-> ");
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stdin);
|
||||
|
||||
|
||||
fgets(S, 50, stdin);
|
||||
|
||||
for (J = 0; S[J] >= ' '; J++)
|
||||
S[J] = toupper(S[J]);
|
||||
|
||||
S[J] = '\0';
|
||||
|
||||
|
||||
switch (S[0])
|
||||
{
|
||||
case 'H':
|
||||
case '?':
|
||||
puts("\n***** Built-in 6502 Debugger Commands *****");
|
||||
puts("<CR> : Break at the next instruction");
|
||||
puts("= <addr> : Break at addr");
|
||||
puts("+ <offset> : Break at PC + offset");
|
||||
puts("t <addr> : Set PC to addr");
|
||||
puts("c : Continue without break");
|
||||
puts("j <addr> : Continue from addr");
|
||||
puts("m <addr> : Memory dump at addr");
|
||||
puts("d <addr> : Disassembly at addr");
|
||||
puts("v : Show ;interrupt vectors");
|
||||
puts("?,h : Show this help text");
|
||||
puts("r : Show Register Status");
|
||||
puts("q : Exit 6502 emulation");
|
||||
|
||||
puts("----- TI-NES Specific -----");
|
||||
puts("w : Dump Memory State");
|
||||
puts("o : Show PPU registers");
|
||||
puts("p <addr> : Dump PPU memory at addr");
|
||||
puts("a : Dump all memory to memory.log");
|
||||
puts("s : Dump sprite table to sprite.log");
|
||||
puts("n <nb> : Dump name table <nb> to nt.log");
|
||||
puts("z : Dump mapper status");
|
||||
puts("i : SpriteTable Dump");
|
||||
puts("g <nb> : Get sprite <nb> info");
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
return (1);
|
||||
|
||||
case 'Z':
|
||||
mapper_dump(stdout);
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
DumpMemoryState(stdout);
|
||||
break;
|
||||
|
||||
|
||||
case 'A':
|
||||
{
|
||||
|
||||
FILE * fpDmpMem;
|
||||
|
||||
if ((fpDmpMem = fopen("memory.log", "wb")) != NULL)
|
||||
|
||||
{
|
||||
|
||||
// fwrite(Memory, 1, 0x8000, fpDmpMem);
|
||||
//fwrite(mLBank, 1, 0x4000, fpDmpMem);
|
||||
//fwrite(mUBank, 1, 0x4000, fpDmpMem);
|
||||
|
||||
fclose(fpDmpMem);
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case '=':
|
||||
if (strlen(S) >= 2)
|
||||
|
||||
{
|
||||
sscanf(S + 1, "%hX", &(R->Trap));
|
||||
R->Trace = 0;
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
if (strlen(S) >= 2)
|
||||
|
||||
{
|
||||
|
||||
sscanf(S + 1, "%hX", &(R->Trap));
|
||||
|
||||
R->Trap += R->PC.W;
|
||||
R->Trace = 0;
|
||||
|
||||
return (1);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
if (strlen(S) >= 2)
|
||||
|
||||
{
|
||||
sscanf(S + 1, "%hX", &(R->PC.W));
|
||||
R->Trace = 0;
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (strlen(S) >= 2)
|
||||
|
||||
{
|
||||
sscanf(S + 1, "%hX", &(R->PC.W));
|
||||
R->Trace = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
R->Trap = 0xFFFF;
|
||||
R->Trace = 0;
|
||||
install_keyboard();
|
||||
|
||||
//ResumeSound();
|
||||
|
||||
SetSound(0, SND_RECTANGLE);
|
||||
SetSound(1, SND_RECTANGLE);
|
||||
SetSound(2, SND_TRIANGLE);
|
||||
SetSound(3, SND_NOISE);
|
||||
|
||||
return (1);
|
||||
|
||||
case 'Q':
|
||||
return (0);
|
||||
|
||||
|
||||
case 'V':
|
||||
puts("\n6502 Interrupt Vectors:");
|
||||
printf("[$FFFC] INIT: $%04X\n", Rd6502(0xFFFC) + 256 * Rd6502(0xFFFD));
|
||||
printf("[$FFFE] IRQ: $%04X\n", Rd6502(0xFFFE) + 256 * Rd6502(0xFFFF));
|
||||
printf("[$FFFA] NMI: $%04X\n", Rd6502(0xFFFA) + 256 * Rd6502(0xFFFB));
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
{
|
||||
word Addr;
|
||||
|
||||
if (strlen(S) > 1)
|
||||
sscanf(S + 1, "%hX", &Addr);
|
||||
else
|
||||
Addr = R->PC.W;
|
||||
puts("");
|
||||
for (J = 0; J < 16; J++)
|
||||
{
|
||||
printf("%04X: ", Addr);
|
||||
for (I = 0; I < 16; I++, Addr++)
|
||||
|
||||
printf("%02X ", Rd6502(Addr));
|
||||
|
||||
printf(" | ");
|
||||
Addr -= 16;
|
||||
|
||||
for (I = 0; I < 16; I++, Addr++)
|
||||
|
||||
putchar(isprint(Rd6502(Addr)) ? Rd6502(Addr) : '.');
|
||||
|
||||
puts("");
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
|
||||
printf
|
||||
(
|
||||
"A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
|
||||
R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
|
||||
);
|
||||
|
||||
|
||||
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
|
||||
|
||||
printf("%c", F & 0x80 ? FA[J] : '.');
|
||||
|
||||
puts("]");
|
||||
|
||||
|
||||
printf
|
||||
(
|
||||
"AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
|
||||
Rd6502(R->PC.W), S,
|
||||
Rd6502(0x0100 + (byte) (R->S + 1)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 2)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 3))
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'D':
|
||||
|
||||
{
|
||||
|
||||
word Addr;
|
||||
|
||||
|
||||
if (strlen(S) > 1)
|
||||
sscanf(S + 1, "%hX", &Addr);
|
||||
else
|
||||
Addr = R->PC.W;
|
||||
|
||||
puts("");
|
||||
|
||||
for (J = 0; J < 16; J++)
|
||||
|
||||
{
|
||||
|
||||
printf("%04X: ", Addr);
|
||||
|
||||
Addr += DAsm(S, Addr);
|
||||
|
||||
puts(S);
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Continue with emulation */
|
||||
return (1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* DEBUG */
|
||||
@ -1,516 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** M6502.c **/
|
||||
/** **/
|
||||
/** This file contains implementation for 6502 CPU. Don't **/
|
||||
/** forget to provide Rd6502(), Wr6502(), Loop6502(), and **/
|
||||
/** possibly Op6502() functions to accomodate the emulated **/
|
||||
/** machine's architecture. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** Alex Krasivsky 1996 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate$
|
||||
* $Author$
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include "M6502.h"
|
||||
#include "Tables.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/** INLINE ***************************************************/
|
||||
/** Different compilers inline C functions differently. **/
|
||||
/*************************************************************/
|
||||
#ifdef __GNUC__
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE static
|
||||
#endif
|
||||
|
||||
int icount = 0;
|
||||
|
||||
/** System-Dependent Stuff ***********************************/
|
||||
/** This is system-dependent code put here to speed things **/
|
||||
/** up. It has to stay inlined to be fast. **/
|
||||
/*************************************************************/
|
||||
#ifdef INES
|
||||
#define FAST_RDOP
|
||||
extern byte *Page[];
|
||||
INLINE byte Op6502(register word A) { return(Page[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
/** FAST_RDOP ************************************************/
|
||||
/** With this #define not present, Rd6502() should perform **/
|
||||
/** the functions of Rd6502(). **/
|
||||
/*************************************************************/
|
||||
#ifndef FAST_RDOP
|
||||
#define Op6502(A) Rd6502(A)
|
||||
#endif
|
||||
|
||||
/** Addressing Methods ***************************************/
|
||||
/** These macros calculate and return effective addresses. **/
|
||||
/*************************************************************/
|
||||
#define MC_Ab(Rg) M_LDWORD(Rg)
|
||||
#define MC_Zp(Rg) Rg.W=Op6502(R->PC.W++)
|
||||
#define MC_Zx(Rg) Rg.W=(byte)(Op6502(R->PC.W++)+R->X)
|
||||
#define MC_Zy(Rg) Rg.W=(byte)(Op6502(R->PC.W++)+R->Y)
|
||||
#define MC_Ax(Rg) M_LDWORD(Rg);Rg.W+=R->X
|
||||
#define MC_Ay(Rg) M_LDWORD(Rg);Rg.W+=R->Y
|
||||
#define MC_Ix(Rg) K.W=(byte)(Op6502(R->PC.W++)+R->X); \
|
||||
Rg.B.l=Op6502(K.W++);Rg.B.h=Op6502(K.W)
|
||||
#define MC_Iy(Rg) K.W=Op6502(R->PC.W++); \
|
||||
Rg.B.l=Op6502(K.W++);Rg.B.h=Op6502(K.W); \
|
||||
Rg.W+=R->Y
|
||||
|
||||
/** Reading From Memory **************************************/
|
||||
/** These macros calculate address and read from it. **/
|
||||
/*************************************************************/
|
||||
#define MR_Ab(Rg) MC_Ab(J);Rg=Rd6502(J.W)
|
||||
#define MR_Im(Rg) Rg=Op6502(R->PC.W++)
|
||||
#define MR_Zp(Rg) MC_Zp(J);Rg=Rd6502(J.W)
|
||||
#define MR_Zx(Rg) MC_Zx(J);Rg=Rd6502(J.W)
|
||||
#define MR_Zy(Rg) MC_Zy(J);Rg=Rd6502(J.W)
|
||||
#define MR_Ax(Rg) MC_Ax(J);Rg=Rd6502(J.W)
|
||||
#define MR_Ay(Rg) MC_Ay(J);Rg=Rd6502(J.W)
|
||||
#define MR_Ix(Rg) MC_Ix(J);Rg=Rd6502(J.W)
|
||||
#define MR_Iy(Rg) MC_Iy(J);Rg=Rd6502(J.W)
|
||||
|
||||
/** Writing To Memory ****************************************/
|
||||
/** These macros calculate address and write to it. **/
|
||||
/*************************************************************/
|
||||
#define MW_Ab(Rg) MC_Ab(J);Wr6502(J.W,Rg)
|
||||
#define MW_Zp(Rg) MC_Zp(J);Wr6502(J.W,Rg)
|
||||
#define MW_Zx(Rg) MC_Zx(J);Wr6502(J.W,Rg)
|
||||
#define MW_Zy(Rg) MC_Zy(J);Wr6502(J.W,Rg)
|
||||
#define MW_Ax(Rg) MC_Ax(J);Wr6502(J.W,Rg)
|
||||
#define MW_Ay(Rg) MC_Ay(J);Wr6502(J.W,Rg)
|
||||
#define MW_Ix(Rg) MC_Ix(J);Wr6502(J.W,Rg)
|
||||
#define MW_Iy(Rg) MC_Iy(J);Wr6502(J.W,Rg)
|
||||
|
||||
/** Modifying Memory *****************************************/
|
||||
/** These macros calculate address and modify it. **/
|
||||
/*************************************************************/
|
||||
#define MM_Ab(Cmd) MC_Ab(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
|
||||
#define MM_Zp(Cmd) MC_Zp(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
|
||||
#define MM_Zx(Cmd) MC_Zx(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
|
||||
#define MM_Ax(Cmd) MC_Ax(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
|
||||
|
||||
/** Other Macros *********************************************/
|
||||
/** Calculating flags, stack, jumps, arithmetics, etc. **/
|
||||
/*************************************************************/
|
||||
#define M_FL(Rg) R->P=(R->P&~(Z_FLAG|N_FLAG))|ZNTable[Rg]
|
||||
#define M_LDWORD(Rg) Rg.B.l=Op6502(R->PC.W++);Rg.B.h=Op6502(R->PC.W++)
|
||||
|
||||
#define M_PUSH(Rg) Wr6502(0x0100|R->S,Rg);R->S--
|
||||
#define M_POP(Rg) R->S++;Rg=Op6502(0x0100|R->S)
|
||||
#define M_JR R->PC.W+=(offset)Op6502(R->PC.W)+1;R->ICount--
|
||||
|
||||
#ifdef NO_DECIMAL
|
||||
|
||||
#define M_ADC(Rg) \
|
||||
K.W=R->A+Rg+(R->P&C_FLAG); \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=(~(R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
|
||||
(K.B.h? C_FLAG:0)|ZNTable[K.B.l]; \
|
||||
R->A=K.B.l
|
||||
|
||||
/* Warning! C_FLAG is inverted before SBC and after it */
|
||||
#define M_SBC(Rg) \
|
||||
K.W=R->A-Rg-(~R->P&C_FLAG); \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=((R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
|
||||
(K.B.h? 0:C_FLAG)|ZNTable[K.B.l]; \
|
||||
R->A=K.B.l
|
||||
|
||||
#else /* NO_DECIMAL */
|
||||
|
||||
#define M_ADC(Rg) \
|
||||
if(R->P&D_FLAG) \
|
||||
{ \
|
||||
K.B.l=(R->A&0x0F)+(Rg&0x0F)+(R->P&C_FLAG); \
|
||||
if(K.B.l>9) K.B.l+=6; \
|
||||
K.B.h=(R->A>>4)+(Rg>>4)+(K.B.l>15? 1:0); \
|
||||
R->A=(K.B.l&0x0F)|(K.B.h<<4); \
|
||||
R->P=(R->P&~C_FLAG)|(K.B.h>15? C_FLAG:0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
K.W=R->A+Rg+(R->P&C_FLAG); \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=(~(R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
|
||||
(K.B.h? C_FLAG:0)|ZNTable[K.B.l]; \
|
||||
R->A=K.B.l; \
|
||||
}
|
||||
|
||||
/* Warning! C_FLAG is inverted before SBC and after it */
|
||||
#define M_SBC(Rg) \
|
||||
if(R->P&D_FLAG) \
|
||||
{ \
|
||||
K.B.l=(R->A&0x0F)-(Rg&0x0F)-(~R->P&C_FLAG); \
|
||||
if(K.B.l&0x10) K.B.l-=6; \
|
||||
K.B.h=(R->A>>4)-(Rg>>4)-((K.B.l&0x10)>>4); \
|
||||
if(K.B.h&0x10) K.B.h-=6; \
|
||||
R->A=(K.B.l&0x0F)|(K.B.h<<4); \
|
||||
R->P=(R->P&~C_FLAG)|(K.B.h>15? 0:C_FLAG); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
K.W=R->A-Rg-(~R->P&C_FLAG); \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=((R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
|
||||
(K.B.h? 0:C_FLAG)|ZNTable[K.B.l]; \
|
||||
R->A=K.B.l; \
|
||||
}
|
||||
|
||||
#endif /* NO_DECIMAL */
|
||||
|
||||
#define M_CMP(Rg1,Rg2) \
|
||||
K.W=Rg1-Rg2; \
|
||||
R->P&=~(N_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=ZNTable[K.B.l]|(K.B.h? 0:C_FLAG)
|
||||
#define M_BIT(Rg) \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG); \
|
||||
R->P|=(Rg&(N_FLAG|V_FLAG))|(Rg&R->A? 0:Z_FLAG)
|
||||
|
||||
#define M_AND(Rg) R->A&=Rg;M_FL(R->A)
|
||||
#define M_ORA(Rg) R->A|=Rg;M_FL(R->A)
|
||||
#define M_EOR(Rg) R->A^=Rg;M_FL(R->A)
|
||||
#define M_INC(Rg) Rg++;M_FL(Rg)
|
||||
#define M_DEC(Rg) Rg--;M_FL(Rg)
|
||||
|
||||
#define M_ASL(Rg) R->P&=~C_FLAG;R->P|=Rg>>7;Rg<<=1;M_FL(Rg)
|
||||
#define M_LSR(Rg) R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg>>=1;M_FL(Rg)
|
||||
#define M_ROL(Rg) K.B.l=(Rg<<1)|(R->P&C_FLAG); \
|
||||
R->P&=~C_FLAG;R->P|=Rg>>7;Rg=K.B.l; \
|
||||
M_FL(Rg)
|
||||
#define M_ROR(Rg) K.B.l=(Rg>>1)|(R->P<<7); \
|
||||
R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg=K.B.l; \
|
||||
M_FL(Rg)
|
||||
|
||||
/** Reset6502() **********************************************/
|
||||
/** This function can be used to reset the registers before **/
|
||||
/** starting execution with Run6502(). It sets registers to **/
|
||||
/** their initial values. **/
|
||||
/*************************************************************/
|
||||
void Reset6502(M6502 *R)
|
||||
{
|
||||
R->A=R->X=R->Y=0x00;
|
||||
R->P=Z_FLAG;
|
||||
R->S=0xFF;
|
||||
R->PC.B.l=Rd6502(0xFFFC);
|
||||
R->PC.B.h=Rd6502(0xFFFD);
|
||||
R->ICount=R->IPeriod;
|
||||
R->IRequest=INT_NONE;
|
||||
R->AfterCLI=0;
|
||||
}
|
||||
|
||||
/** Exec6502() ***********************************************/
|
||||
/** This function will execute a single 6502 opcode. It **/
|
||||
/** will then return next PC, and current register values **/
|
||||
/** in R. **/
|
||||
/*************************************************************/
|
||||
word Exec6502(M6502 *R)
|
||||
{
|
||||
register pair J,K;
|
||||
register byte I;
|
||||
|
||||
I=Op6502(R->PC.W++);
|
||||
R->ICount-=Cycles[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
}
|
||||
|
||||
/* We are done */
|
||||
return(R->PC.W);
|
||||
}
|
||||
|
||||
/** Int6502() ************************************************/
|
||||
/** This function will generate interrupt of a given type. **/
|
||||
/** INT_NMI will cause a non-maskable interrupt. INT_IRQ **/
|
||||
/** will cause a normal interrupt, unless I_FLAG set in R. **/
|
||||
/*************************************************************/
|
||||
void Int6502(M6502 *R,byte Type)
|
||||
{
|
||||
register pair J;
|
||||
|
||||
if((Type==INT_NMI)||((Type==INT_IRQ)&&!(R->P&I_FLAG)))
|
||||
{
|
||||
R->ICount-=7;
|
||||
M_PUSH(R->PC.B.h);
|
||||
M_PUSH(R->PC.B.l);
|
||||
M_PUSH(R->P & ~(B_FLAG|R_FLAG));
|
||||
R->P&=~D_FLAG;
|
||||
if(R->IAutoReset&&(Type==R->IRequest)) R->IRequest=INT_NONE;
|
||||
if(Type==INT_NMI) J.W=0xFFFA; else { R->P|=I_FLAG;J.W=0xFFFE; }
|
||||
R->PC.B.l=Rd6502(J.W++);
|
||||
R->PC.B.h=Rd6502(J.W);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TRACE_EXECUTION
|
||||
|
||||
enum Addressing_Modes
|
||||
{
|
||||
Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
|
||||
};
|
||||
|
||||
static char *mnCAP[] =
|
||||
{
|
||||
"ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI",
|
||||
"BNE", "BPL", "BRK", "BVC", "BVS", "CLC", "CLD", "CLI",
|
||||
"CLV", "CMP", "CPX", "CPY", "DEC", "DEX", "DEY", "INX",
|
||||
"INY", "EOR", "INC", "JMP", "JSR", "LDA", "NOP", "LDX",
|
||||
"LDY", "LSR", "ORA", "PHA", "PHP", "PLA", "PLP", "ROL",
|
||||
"ROR", "RTI", "RTS", "SBC", "STA", "STX", "STY", "SEC",
|
||||
"SED", "SEI", "TAX", "TAY", "TXA", "TYA", "TSX", "TXS"
|
||||
};
|
||||
|
||||
#define DAsm DAsmCAP
|
||||
|
||||
static byte ad[512] =
|
||||
{
|
||||
10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
|
||||
36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
|
||||
9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
|
||||
13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
|
||||
28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
|
||||
38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
|
||||
7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
|
||||
47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
|
||||
41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
|
||||
35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
|
||||
11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
|
||||
15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
|
||||
42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
|
||||
37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
|
||||
12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
|
||||
49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
|
||||
No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
|
||||
22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
|
||||
3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
|
||||
53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
|
||||
32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
|
||||
51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
|
||||
4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
|
||||
16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
|
||||
19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
|
||||
24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
|
||||
8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
|
||||
14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
|
||||
18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
|
||||
23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
|
||||
5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
|
||||
48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
|
||||
};
|
||||
|
||||
#define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
|
||||
|
||||
/** DAsm() ****************************************************/
|
||||
/** This function will disassemble a single command and **/
|
||||
/** return the number of bytes disassembled. **/
|
||||
/**************************************************************/
|
||||
int DAsmCAP(char *S, word A)
|
||||
{
|
||||
|
||||
byte J;
|
||||
|
||||
word B, OP, TO;
|
||||
|
||||
|
||||
B = A;
|
||||
OP = Rd6502(B++) * 2;
|
||||
|
||||
|
||||
switch (ad[OP + 1])
|
||||
|
||||
{
|
||||
|
||||
case Ac:
|
||||
sprintf(S, "%s A", mnCAP[ad[OP]]);
|
||||
break;
|
||||
|
||||
case Il:
|
||||
sprintf(S, "%s", mnCAP[ad[OP]]);
|
||||
break;
|
||||
|
||||
|
||||
case Rl:
|
||||
J = Rd6502(B++);
|
||||
TO = A + 2 + ((J < 0x80) ? J : (J - 256));
|
||||
|
||||
sprintf(S, "%s $%04x", mnCAP[ad[OP]], TO);
|
||||
break;
|
||||
|
||||
|
||||
case Im:
|
||||
sprintf(S, "%s #$%02x", mnCAP[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zp:
|
||||
sprintf(S, "%s $%02x", mnCAP[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zx:
|
||||
sprintf(S, "%s $%02x,X", mnCAP[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zy:
|
||||
sprintf(S, "%s $%02x,Y", mnCAP[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Ix:
|
||||
sprintf(S, "%s ($%02x,X)", mnCAP[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Iy:
|
||||
sprintf(S, "%s ($%02x),Y", mnCAP[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
|
||||
case Ab:
|
||||
sprintf(S, "%s $%04x", mnCAP[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case Ax:
|
||||
sprintf(S, "%s $%04x,X", mnCAP[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case Ay:
|
||||
sprintf(S, "%s $%04x,Y", mnCAP[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case In:
|
||||
sprintf(S, "%s ($%04x)", mnCAP[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
sprintf(S, ".db $%02x; <Invalid OPcode>", OP / 2);
|
||||
|
||||
}
|
||||
return (B - A);
|
||||
|
||||
}
|
||||
|
||||
extern unsigned short ScanLine;
|
||||
|
||||
#endif
|
||||
|
||||
/** Run6502() ************************************************/
|
||||
/** This function will run 6502 code until Loop6502() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
word Run6502(M6502 *R)
|
||||
{
|
||||
register pair J,K;
|
||||
register byte I;
|
||||
byte nb_of_cycle;
|
||||
for(;;)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Turn tracing on when reached trap address */
|
||||
if(R->PC.W==R->Trap) R->Trace=1;
|
||||
/* Call single-step debugger, exit if requested */
|
||||
if(R->Trace)
|
||||
if(!Debug6502(R)) return(R->PC.W);
|
||||
#endif
|
||||
|
||||
#ifdef TRACE_EXECUTION
|
||||
while(1)
|
||||
{
|
||||
|
||||
static char FA[8] = "NV.BDIZC";
|
||||
char S[128];
|
||||
byte F;
|
||||
int J, I;
|
||||
|
||||
DAsm(S, R->PC.W);
|
||||
|
||||
printf
|
||||
(
|
||||
"AT PC: [%02x - %s]\n",
|
||||
Rd6502(R->PC.W), S
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
I=Op6502(R->PC.W++);
|
||||
nb_of_cycle = Cycles[I];
|
||||
//#ifdef DEBUG
|
||||
// pushop(I);
|
||||
//#endif
|
||||
icount++;
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
}
|
||||
#ifdef TRACE_EXECUTION
|
||||
while(1)
|
||||
{
|
||||
static char FA[8] = "NV.BDIZC";
|
||||
char S[128];
|
||||
byte F;
|
||||
int J, I;
|
||||
|
||||
printf
|
||||
(
|
||||
"A:%02x X:%02x Y:%02x S:%04x, PC:%04x Flags:[",
|
||||
R->A, R->X, R->Y, R->S + 0x0100, R->PC.W
|
||||
);
|
||||
|
||||
|
||||
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
|
||||
|
||||
printf("%c", F & 0x80 ? FA[J] : '.');
|
||||
|
||||
printf("], Stack[%02x, %02x, %02x], %03d, %03d\n",
|
||||
Rd6502(0x0100 + (byte) (R->S + 1)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 2)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 3)),
|
||||
R->ICount,
|
||||
ScanLine
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
R->ICount-= nb_of_cycle;
|
||||
/* If cycle counter expired... */
|
||||
if(R->ICount<=0)
|
||||
{
|
||||
/* If we have come after CLI, get INT_? from IRequest */
|
||||
/* Otherwise, get it from the loop handler */
|
||||
if(R->AfterCLI)
|
||||
{
|
||||
I=R->IRequest; /* Get pending interrupt */
|
||||
R->ICount+=R->IBackup-1; /* Restore the ICount */
|
||||
R->AfterCLI=0; /* Done with AfterCLI state */
|
||||
}
|
||||
else
|
||||
{
|
||||
I=Loop6502(R); /* Call the periodic handler */
|
||||
R->ICount+=R->IPeriod; /* Reset the cycle counter */
|
||||
if(!I) I=R->IRequest; /* Realize pending interrupt */
|
||||
}
|
||||
|
||||
if(I==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT */
|
||||
if(I) Int6502(R,I); /* Interrupt if needed */
|
||||
}
|
||||
}
|
||||
|
||||
/* Execution stopped */
|
||||
return(R->PC.W);
|
||||
}
|
||||
@ -1,148 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** M6502.h **/
|
||||
/** **/
|
||||
/** This file contains declarations relevant to emulation **/
|
||||
/** of 6502 CPU. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** Alex Krasivsky 1996 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate$
|
||||
* $Author$
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#ifndef M6502_H
|
||||
#define M6502_H
|
||||
/* Loop6502() returns: */
|
||||
#define INT_NONE 0 /* No interrupt required */
|
||||
#define INT_IRQ 1 /* Standard IRQ interrupt */
|
||||
#define INT_NMI 2 /* Non-maskable interrupt */
|
||||
#define INT_QUIT 3 /* Exit the emulation */
|
||||
|
||||
/* 6502 status flags: */
|
||||
#define C_FLAG 0x01 /* 1: Carry occured */
|
||||
#define Z_FLAG 0x02 /* 1: Result is zero */
|
||||
#define I_FLAG 0x04 /* 1: Interrupts disabled */
|
||||
#define D_FLAG 0x08 /* 1: Decimal mode */
|
||||
#define B_FLAG 0x10 /* Break [0 on stk after int] */
|
||||
#define R_FLAG 0x20 /* Always 1 */
|
||||
#define V_FLAG 0x40 /* 1: Overflow occured */
|
||||
#define N_FLAG 0x80 /* 1: Result is negative */
|
||||
|
||||
/** Simple Datatypes *****************************************/
|
||||
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/
|
||||
/*************************************************************/
|
||||
#ifndef BYTE_TYPE_DEFINED
|
||||
#define BYTE_TYPE_DEFINED
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
#ifndef WORD_TYPE_DEFINED
|
||||
#define WORD_TYPE_DEFINED
|
||||
typedef unsigned short word;
|
||||
#endif
|
||||
typedef signed char offset;
|
||||
|
||||
/** Structured Datatypes *************************************/
|
||||
/** NOTICE: #define LSB_FIRST for machines where least **/
|
||||
/** signifcant byte goes first. **/
|
||||
/*************************************************************/
|
||||
typedef union
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
struct { byte l,h; } B;
|
||||
#else
|
||||
struct { byte h,l; } B;
|
||||
#endif
|
||||
word W;
|
||||
} pair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte A,P,X,Y,S; /* CPU registers and program counter */
|
||||
pair PC;
|
||||
|
||||
int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */
|
||||
/* between calls to Loop6502() */
|
||||
byte IRequest; /* Set to the INT_IRQ when pending IRQ */
|
||||
byte AfterCLI; /* Private, don't touch */
|
||||
int IBackup; /* Private, don't touch */
|
||||
byte IAutoReset; /* Set to 1 to autom. reset IRequest */
|
||||
byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */
|
||||
word Trap; /* Set Trap to address to trace from */
|
||||
byte Trace; /* Set Trace=1 to start tracing */
|
||||
void *User; /* Arbitrary user data (ID,RAM*,etc.) */
|
||||
} M6502;
|
||||
|
||||
/** Reset6502() **********************************************/
|
||||
/** This function can be used to reset the registers before **/
|
||||
/** starting execution with Run6502(). It sets registers to **/
|
||||
/** their initial values. **/
|
||||
/*************************************************************/
|
||||
void Reset6502(register M6502 *R);
|
||||
|
||||
/** Exec6502() ***********************************************/
|
||||
/** This function will execute a single 6502 opcode. It **/
|
||||
/** will then return next PC, and current register values **/
|
||||
/** in R. **/
|
||||
/*************************************************************/
|
||||
word Exec6502(register M6502 *R);
|
||||
|
||||
/** Int6502() ************************************************/
|
||||
/** This function will generate interrupt of a given type. **/
|
||||
/** INT_NMI will cause a non-maskable interrupt. INT_IRQ **/
|
||||
/** will cause a normal interrupt, unless I_FLAG set in R. **/
|
||||
/*************************************************************/
|
||||
void Int6502(register M6502 *R,register byte Type);
|
||||
|
||||
/** Run6502() ************************************************/
|
||||
/** This function will run 6502 code until Loop6502() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
word Run6502(register M6502 *R);
|
||||
|
||||
/** Rd6502()/Wr6502/Op6502() *********************************/
|
||||
/** These functions are called when access to RAM occurs. **/
|
||||
/** They allow to control memory access. Op6502 is the same **/
|
||||
/** as Rd6502, but used to read *opcodes* only, when many **/
|
||||
/** checks can be skipped to make it fast. It is only **/
|
||||
/** required if there is a #define FAST_RDOP. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void Wr6502(register word Addr,register byte Value);
|
||||
byte Rd6502(register word Addr);
|
||||
byte Op6502(register word Addr);
|
||||
|
||||
/** Debug6502() **********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the 6502 registers. Emulation exits **/
|
||||
/** if Debug6502() returns 0. **/
|
||||
/*************************************************************/
|
||||
byte Debug6502(register M6502 *R);
|
||||
|
||||
/** Loop6502() ***********************************************/
|
||||
/** 6502 emulation calls this function periodically to **/
|
||||
/** check if the system hardware requires any interrupts. **/
|
||||
/** This function must return one of following values: **/
|
||||
/** INT_NONE, INT_IRQ, INT_NMI, or INT_QUIT to exit the **/
|
||||
/** emulation loop. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
byte Loop6502(register M6502 *R);
|
||||
|
||||
/** Patch6502() **********************************************/
|
||||
/** Emulation calls this function when it encounters an **/
|
||||
/** unknown opcode. This can be used to patch the code to **/
|
||||
/** emulate BIOS calls, such as disk and tape access. The **/
|
||||
/** function should return 1 if the exception was handled, **/
|
||||
/** or 0 if the opcode was truly illegal. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
byte Patch6502(register byte Op,register M6502 *R);
|
||||
|
||||
#endif /* M6502_H */
|
||||
@ -1,71 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** Tables.h **/
|
||||
/** **/
|
||||
/** This file contains tables of used by 6502 emulation to **/
|
||||
/** compute NEGATIVE and ZERO flags. There are also timing **/
|
||||
/** tables for 6502 opcodes. This file is included from **/
|
||||
/** 6502.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate$
|
||||
* $Author$
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
static byte Cycles[256] =
|
||||
{
|
||||
7, 6, 2, 1, 5, 3, 5, 5, 3, 2, 2, 1, 6, 4, 6, 2,
|
||||
2, 5, 5, 1, 5, 4, 6, 5, 2, 4, 2, 1, 6, 4, 6, 2,
|
||||
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 4, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 2, 1, 4, 4, 6, 2,
|
||||
6, 6, 2, 1, 3, 3, 5, 5, 3, 2, 2, 1, 3, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 1, 8, 4, 6, 2,
|
||||
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 6, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 5, 4, 4, 1, 6, 4, 6, 2,
|
||||
3, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 2,
|
||||
2, 6, 5, 1, 4, 4, 4, 5, 2, 5, 2, 1, 4, 5, 5, 2,
|
||||
2, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 2,
|
||||
2, 5, 5, 1, 4, 4, 4, 5, 2, 4, 2, 1, 4, 4, 4, 2,
|
||||
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 2, 4, 4, 6, 2,
|
||||
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 1, 4, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 4, 1, 4, 4, 6, 2
|
||||
};
|
||||
|
||||
|
||||
byte ZNTable[256] =
|
||||
{
|
||||
|
||||
Z_FLAG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user