Remove Marat Fayzullin 6502 emulation code

This commit is contained in:
Godzil 2018-01-30 17:29:26 +00:00
parent 12663ba99a
commit e96f36b6de
5 changed files with 0 additions and 2055 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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,
};