📄 cpu.cpp
字号:
/*----------------------------------------------------------------------*/
/* */
/* 6502 CPU Core v0.00 */
/* Norix */
/* written 2000/12/23 */
/* last modify ----/--/-- */
/*----------------------------------------------------------------------*/
/*--------------[ INCLUDE ]-------------------------------*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "VirtuaNESres.h"
#include "typedef.h"
#include "macro.h"
#include "DebugOut.h"
#include "App.h"
#include "Config.h"
#include "nes.h"
#include "mmu.h"
#include "cpu.h"
#include "apu.h"
#include "rom.h"
#include "mapper.h"
/*--------------[ DEFINE ]-------------------------------*/
#define DPCM_SYNCCLOCK FALSE
/*--------------[ EXTERNAL PROGRAM ]-------------------------------*/
/*--------------[ EXTERNAL WORK ]-------------------------------*/
/*--------------[ WORK ]-------------------------------*/
/*--------------[ CONST ]-------------------------------*/
/*--------------[ PROTOTYPE ]-------------------------------*/
/*--------------[ PROGRAM ]-------------------------------*/
// 僆儁僐乕僪
//#define OP6502(A) RD6502((A))
//#define OP6502W(A) RD6502W((A))
// 僛儘儁乕僕儕乕僪
#define ZPRD(A) (RAM[(BYTE)(A)])
//#define ZPRDW(A) (*((LPWORD)&RAM[(BYTE)(A)]))
#define ZPRDW(A) ((WORD)RAM[(BYTE)(A)]+((WORD)RAM[(BYTE)((A)+1)]<<8))
#define ZPWR(A,V) { RAM[(BYTE)(A)]=(V); }
#define ZPWRW(A,V) { *((LPWORD)&RAM[(BYTE)(A)])=(WORD)(V); }
// 僒僀僋儖僇僂儞僞
#define ADD_CYCLE(V) { exec_cycles += (V); }
//#define ADD_CYCLE(V) {}
// EFFECTIVE ADDRESS儁乕僕嫬奅挻偊僠僃僢僋
#define CHECK_EA() { if( (ET&0xFF00) != (EA&0xFF00) ) ADD_CYCLE(1); }
//#define CHECK_EA() { if( (R.PC&0xFF00) != (EA&0xFF00) ) ADD_CYCLE(1); }
//#define CHECK_EA() {}
// 僼儔僌憖嶌
// 僛儘乛僱僈僥傿僽僼儔僌偺僠僃僢僋偲愝掕
#define SET_ZN_FLAG(A) { R.P &= ~(Z_FLAG|N_FLAG); R.P |= ZN_Table[(BYTE)(A)]; }
// 僼儔僌僙僢僩
#define SET_FLAG(V) { R.P |= (V); }
// 僼儔僌僋儕傾
#define CLR_FLAG(V) { R.P &= ~(V); }
// 僼儔僌僥僗僩仌僙僢僩乛僋儕傾
#define TST_FLAG(F,V) { R.P &= ~(V); if((F)) R.P |= (V); }
// 僼儔僌僠僃僢僋
#define CHK_FLAG(V) (R.P&(V))
// WT .... WORD TEMP
// EA .... EFFECTIVE ADDRESS
// ET .... EFFECTIVE ADDRESS TEMP
// DT .... DATA
#define MR_IM() { \
DT = OP6502( R.PC++ ); \
}
#define MR_ZP() { \
EA = OP6502( R.PC++ ); \
DT = ZPRD( EA ); \
}
#define MR_ZX() { \
DT = OP6502( R.PC++ ); \
EA = (BYTE)(DT + R.X); \
DT = ZPRD( EA ); \
}
#define MR_ZY() { \
DT = OP6502( R.PC++ ); \
EA = (BYTE)(DT + R.Y); \
DT = ZPRD( EA ); \
}
#define MR_AB() { \
EA = OP6502W( R.PC ); \
R.PC += 2; \
DT = RD6502( EA ); \
}
#define MR_AX() { \
ET = OP6502W( R.PC ); \
R.PC += 2; \
EA = ET + (WORD)R.X; \
DT = RD6502( EA ); \
}
#define MR_AY() { \
ET = OP6502W( R.PC ); \
R.PC += 2; \
EA = ET + (WORD)R.Y; \
DT = RD6502( EA ); \
}
#define MR_IX() { \
DT = OP6502( R.PC++ ); \
EA = ZPRDW( DT + R.X ); \
DT = RD6502( EA ); \
}
#define MR_IY() { \
DT = OP6502( R.PC++ ); \
ET = ZPRDW( DT ); \
EA = ET + (WORD)R.Y; \
DT = RD6502( EA ); \
}
// EFFECTIVE ADDRESS
#define EA_ZP() { \
EA = OP6502( R.PC++ ); \
}
#define EA_ZX() { \
DT = OP6502( R.PC++ ); \
EA = (BYTE)(DT + R.X); \
}
#define EA_ZY() { \
DT = OP6502( R.PC++ ); \
EA = (BYTE)(DT + R.Y); \
}
#define EA_AB() { \
EA = OP6502W( R.PC ); \
R.PC += 2; \
}
#define EA_AX() { \
ET = OP6502W( R.PC ); \
R.PC += 2; \
EA = ET + R.X; \
}
#define EA_AY() { \
ET = OP6502W( R.PC ); \
R.PC += 2; \
EA = ET + R.Y; \
}
#define EA_IX() { \
DT = OP6502( R.PC++ ); \
EA = ZPRDW( DT + R.X ); \
}
#define EA_IY() { \
DT = OP6502( R.PC++ ); \
ET = ZPRDW( DT ); \
EA = ET + (WORD)R.Y; \
}
// 儊儌儕儔僀僩
#define MW_ZP() ZPWR(EA,DT)
#define MW_EA() WR6502(EA,DT)
// STACK憖嶌
#define PUSH(V) { STACK[(R.S--)&0xFF]=(V); }
#define POP() STACK[(++R.S)&0xFF]
// 嶼弍墘嶼宯
/* ADC (NV----ZC) */
#define ADC() { \
WT = R.A+DT+(R.P&C_FLAG); \
TST_FLAG( WT > 0xFF, C_FLAG ); \
TST_FLAG( ((~(R.A^DT))&(R.A^WT)&0x80), V_FLAG ); \
R.A = (BYTE)WT; \
SET_ZN_FLAG(R.A); \
}
/* SBC (NV----ZC) */
#define SBC() { \
WT = R.A-DT-(~R.P&C_FLAG); \
TST_FLAG( ((R.A^DT) & (R.A^WT)&0x80), V_FLAG ); \
TST_FLAG( WT < 0x100, C_FLAG ); \
R.A = (BYTE)WT; \
SET_ZN_FLAG(R.A); \
}
/* INC (N-----Z-) */
#define INC() { \
DT++; \
SET_ZN_FLAG(DT); \
}
/* INX (N-----Z-) */
#define INX() { \
R.X++; \
SET_ZN_FLAG(R.X); \
}
/* INY (N-----Z-) */
#define INY() { \
R.Y++; \
SET_ZN_FLAG(R.Y); \
}
/* DEC (N-----Z-) */
#define DEC() { \
DT--; \
SET_ZN_FLAG(DT); \
}
/* DEX (N-----Z-) */
#define DEX() { \
R.X--; \
SET_ZN_FLAG(R.X); \
}
/* DEY (N-----Z-) */
#define DEY() { \
R.Y--; \
SET_ZN_FLAG(R.Y); \
}
// 榑棟墘嶼宯
/* AND (N-----Z-) */
#define AND() { \
R.A &= DT; \
SET_ZN_FLAG(R.A); \
}
/* ORA (N-----Z-) */
#define ORA() { \
R.A |= DT; \
SET_ZN_FLAG(R.A); \
}
/* EOR (N-----Z-) */
#define EOR() { \
R.A ^= DT; \
SET_ZN_FLAG(R.A); \
}
/* ASL_A (N-----ZC) */
#define ASL_A() { \
TST_FLAG( R.A&0x80, C_FLAG ); \
R.A <<= 1; \
SET_ZN_FLAG(R.A); \
}
/* ASL (N-----ZC) */
#define ASL() { \
TST_FLAG( DT&0x80, C_FLAG ); \
DT <<= 1; \
SET_ZN_FLAG(DT); \
}
/* LSR_A (N-----ZC) */
#define LSR_A() { \
TST_FLAG( R.A&0x01, C_FLAG ); \
R.A >>= 1; \
SET_ZN_FLAG(R.A); \
}
/* LSR (N-----ZC) */
#define LSR() { \
TST_FLAG( DT&0x01, C_FLAG ); \
DT >>= 1; \
SET_ZN_FLAG(DT); \
}
/* ROL_A (N-----ZC) */
#define ROL_A() { \
if( R.P & C_FLAG ) { \
TST_FLAG(R.A&0x80,C_FLAG); \
R.A = (R.A<<1)|0x01; \
} else { \
TST_FLAG(R.A&0x80,C_FLAG); \
R.A <<= 1; \
} \
SET_ZN_FLAG(R.A); \
}
/* ROL (N-----ZC) */
#define ROL() { \
if( R.P & C_FLAG ) { \
TST_FLAG(DT&0x80,C_FLAG); \
DT = (DT<<1)|0x01; \
} else { \
TST_FLAG(DT&0x80,C_FLAG); \
DT <<= 1; \
} \
SET_ZN_FLAG(DT); \
}
/* ROR_A (N-----ZC) */
#define ROR_A() { \
if( R.P & C_FLAG ) { \
TST_FLAG(R.A&0x01,C_FLAG); \
R.A = (R.A>>1)|0x80; \
} else { \
TST_FLAG(R.A&0x01,C_FLAG); \
R.A >>= 1; \
} \
SET_ZN_FLAG(R.A); \
}
/* ROR (N-----ZC) */
#define ROR() { \
if( R.P & C_FLAG ) { \
TST_FLAG(DT&0x01,C_FLAG); \
DT = (DT>>1)|0x80; \
} else { \
TST_FLAG(DT&0x01,C_FLAG); \
DT >>= 1; \
} \
SET_ZN_FLAG(DT); \
}
/* BIT (NV----Z-) */
#define BIT() { \
TST_FLAG( (DT&R.A)==0, Z_FLAG ); \
TST_FLAG( DT&0x80, N_FLAG ); \
TST_FLAG( DT&0x40, V_FLAG ); \
}
// 儘乕僪乛僗僩傾宯
/* LDA (N-----Z-) */
#define LDA() { R.A = DT; SET_ZN_FLAG(R.A); }
/* LDX (N-----Z-) */
#define LDX() { R.X = DT; SET_ZN_FLAG(R.X); }
/* LDY (N-----Z-) */
#define LDY() { R.Y = DT; SET_ZN_FLAG(R.Y); }
/* STA (--------) */
#define STA() { DT = R.A; }
/* STX (--------) */
#define STX() { DT = R.X; }
/* STY (--------) */
#define STY() { DT = R.Y; }
/* TAX (N-----Z-) */
#define TAX() { R.X = R.A; SET_ZN_FLAG(R.X); }
/* TXA (N-----Z-) */
#define TXA() { R.A = R.X; SET_ZN_FLAG(R.A); }
/* TAY (N-----Z-) */
#define TAY() { R.Y = R.A; SET_ZN_FLAG(R.Y); }
/* TYA (N-----Z-) */
#define TYA() { R.A = R.Y; SET_ZN_FLAG(R.A); }
/* TSX (N-----Z-) */
#define TSX() { R.X = R.S; SET_ZN_FLAG(R.X); }
/* TXS (--------) */
#define TXS() { R.S = R.X; }
// 斾妑宯
/* CMP (N-----ZC) */
#define CMP_() { \
WT = (WORD)R.A - (WORD)DT; \
TST_FLAG( (WT&0x8000)==0, C_FLAG ); \
SET_ZN_FLAG( (BYTE)WT ); \
}
/* CPX (N-----ZC) */
#define CPX() { \
WT = (WORD)R.X - (WORD)DT; \
TST_FLAG( (WT&0x8000)==0, C_FLAG ); \
SET_ZN_FLAG( (BYTE)WT ); \
}
/* CPY (N-----ZC) */
#define CPY() { \
WT = (WORD)R.Y - (WORD)DT; \
TST_FLAG( (WT&0x8000)==0, C_FLAG ); \
SET_ZN_FLAG( (BYTE)WT ); \
}
// 僕儍儞僾乛儕僞乕儞宯
#if 1
#define JMP_ID() { \
WT = OP6502W(R.PC); \
EA = RD6502(WT); \
WT = (WT&0xFF00)|((WT+1)&0x00FF); \
R.PC = EA+RD6502(WT)*0x100; \
}
#else
#define JMP_ID() { \
ET = OP6502W(R.PC); \
EA = RD6502W(ET); \
R.PC = EA; \
}
#endif
#define JMP() { \
R.PC = OP6502W( R.PC ); \
}
#define JSR() { \
EA = OP6502W( R.PC ); \
R.PC++; \
PUSH( R.PC>>8 ); \
PUSH( R.PC&0xFF ); \
R.PC = EA; \
}
#define RTS() { \
R.PC = POP(); \
R.PC |= POP()*0x0100; \
R.PC++; \
}
#define RTI() { \
R.P = POP() | R_FLAG; \
R.PC = POP(); \
R.PC |= POP()*0x0100; \
}
#define _NMI() { \
PUSH( R.PC>>8 ); \
PUSH( R.PC&0xFF ); \
CLR_FLAG( B_FLAG ); \
PUSH( R.P ); \
SET_FLAG( I_FLAG ); \
R.PC = RD6502W(NMI_VECTOR); \
exec_cycles += 7; \
}
#define _IRQ() { \
PUSH( R.PC>>8 ); \
PUSH( R.PC&0xFF ); \
CLR_FLAG( B_FLAG ); \
PUSH( R.P ); \
SET_FLAG( I_FLAG ); \
R.PC = RD6502W(IRQ_VECTOR); \
exec_cycles += 7; \
}
#define BRK() { \
R.PC++; \
PUSH( R.PC>>8 ); \
PUSH( R.PC&0xFF ); \
SET_FLAG( B_FLAG ); \
PUSH( R.P ); \
SET_FLAG( I_FLAG ); \
R.PC = RD6502W(IRQ_VECTOR); \
}
#if 1
#define REL_JUMP() { \
ET = R.PC; \
EA = R.PC + (SBYTE)DT; \
R.PC = EA; \
ADD_CYCLE(1); \
CHECK_EA(); \
}
#else
#define REL_JUMP() { \
R.PC = R.PC + (SBYTE)DT; \
ADD_CYCLE(1); \
}
#endif
#define BCC() { if( !(R.P & C_FLAG) ) REL_JUMP(); }
#define BCS() { if( (R.P & C_FLAG) ) REL_JUMP(); }
#define BNE() { if( !(R.P & Z_FLAG) ) REL_JUMP(); }
#define BEQ() { if( (R.P & Z_FLAG) ) REL_JUMP(); }
#define BPL() { if( !(R.P & N_FLAG) ) REL_JUMP(); }
#define BMI() { if( (R.P & N_FLAG) ) REL_JUMP(); }
#define BVC() { if( !(R.P & V_FLAG) ) REL_JUMP(); }
#define BVS() { if( (R.P & V_FLAG) ) REL_JUMP(); }
// 僼儔僌惂屼宯
#define CLC() { R.P &= ~C_FLAG; }
#define CLD() { R.P &= ~D_FLAG; }
#define CLI() { R.P &= ~I_FLAG; }
#define CLV() { R.P &= ~V_FLAG; }
#define SEC() { R.P |= C_FLAG; }
#define SED() { R.P |= D_FLAG; }
#define SEI() { R.P |= I_FLAG; }
// Unofficial柦椷
#define ANC() { \
R.A &= DT; \
SET_ZN_FLAG( R.A ); \
TST_FLAG( R.P&N_FLAG, C_FLAG ); \
}
#define ANE() { \
R.A = (R.A|0xEE)&R.X&DT; \
SET_ZN_FLAG( R.A ); \
}
#define ARR() { \
DT &= R.A; \
R.A = (DT>>1)|((R.P&C_FLAG)<<7); \
SET_ZN_FLAG( R.A ); \
TST_FLAG( R.A&0x40, C_FLAG ); \
TST_FLAG( (R.A>>6)^(R.A>>5), V_FLAG ); \
}
#define ASR() { \
DT &= R.A; \
TST_FLAG( DT&0x01, C_FLAG ); \
R.A = DT>>1; \
SET_ZN_FLAG( R.A ); \
}
#define DCP() { \
DT--; \
CMP_(); \
}
#define DOP() { \
R.PC++; \
}
#define ISB() { \
DT++; \
SBC(); \
}
#define LAS() { \
R.A = R.X = R.S = (R.S & DT); \
SET_ZN_FLAG( R.A ); \
}
#define LAX() { \
R.A = DT; \
R.X = R.A; \
SET_ZN_FLAG( R.A ); \
}
#define LXA() { \
R.A = R.X = ((R.A|0xEE)&DT); \
SET_ZN_FLAG( R.A ); \
}
#define RLA() { \
if( R.P & C_FLAG ) { \
TST_FLAG( DT&0x80, C_FLAG ); \
DT = (DT<<1)|1; \
} else { \
TST_FLAG( DT&0x80, C_FLAG ); \
DT <<= 1; \
} \
R.A &= DT; \
SET_ZN_FLAG( R.A ); \
}
#define RRA() { \
if( R.P & C_FLAG ) { \
TST_FLAG( DT&0x01, C_FLAG ); \
DT = (DT>>1)|0x80; \
} else { \
TST_FLAG( DT&0x01, C_FLAG ); \
DT >>= 1; \
} \
ADC(); \
}
#define SAX() { \
DT = R.A & R.X; \
}
#define SBX() { \
WT = (R.A&R.X)-DT; \
TST_FLAG( WT < 0x100, C_FLAG ); \
R.X = WT&0xFF; \
SET_ZN_FLAG( R.X ); \
}
#define SHA() { \
DT = R.A & R.X & (BYTE)((EA>>8)+1); \
}
#define SHS() { \
R.S = R.A & R.X; \
DT = R.S & (BYTE)((EA>>8)+1); \
}
#define SHX() { \
DT = R.X & (BYTE)((EA>>8)+1); \
}
#define SHY() { \
DT = R.Y & (BYTE)((EA>>8)+1); \
}
#define SLO() { \
TST_FLAG( DT&0x80, C_FLAG ); \
DT <<= 1; \
R.A |= DT; \
SET_ZN_FLAG( R.A ); \
}
#define SRE() { \
TST_FLAG( DT&0x01, C_FLAG ); \
DT >>= 1; \
R.A ^= DT; \
SET_ZN_FLAG( R.A ); \
}
#define TOP() { \
R.PC += 2; \
}
//
// 僐儞僗僩儔僋僞/僨僗僩儔僋僞
//
//CPU::CPU( NES* parent )
CPU::CPU( NES* parent ) : nes(parent)
{
// nes = parent;
m_bClockProcess = FALSE;
}
CPU::~CPU()
{
}
// 儊儌儕傾僋僙僗
//#define OP6502(A) (CPU_MEM_BANK[(A)>>13][(A)&0x1FFF])
//#define OP6502W(A) (*((WORD*)&CPU_MEM_BANK[(A)>>13][(A)&0x1FFF]))
#if 0
#define OP6502(A) RD6502((A))
#define OP6502W(A) RD6502W((A))
#else
inline BYTE OP6502( WORD addr )
{
return CPU_MEM_BANK[addr>>13][addr&0x1FFF];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -