📄 cpu.cpp
字号:
}
inline WORD OP6502W( WORD addr )
{
#if 0
WORD ret;
ret = (WORD)CPU_MEM_BANK[(addr+0)>>13][(addr+0)&0x1FFF];
ret |= (WORD)CPU_MEM_BANK[(addr+1)>>13][(addr+1)&0x1FFF]<<8;
return ret;
#else
return *((WORD*)&CPU_MEM_BANK[addr>>13][addr&0x1FFF]);
#endif
}
#endif
inline BYTE CPU::RD6502( WORD addr )
{
if( addr < 0x2000 ) {
// RAM (Mirror $0800, $1000, $1800)
return RAM[addr&0x07FF];
} else if( addr < 0x8000 ) {
// Others
return nes->Read( addr );
} else {
// Dummy access
mapper->Read( addr, CPU_MEM_BANK[addr>>13][addr&0x1FFF] );
}
// Quick bank read
return CPU_MEM_BANK[addr>>13][addr&0x1FFF];
}
inline WORD CPU::RD6502W( WORD addr )
{
if( addr < 0x2000 ) {
// RAM (Mirror $0800, $1000, $1800)
return *((WORD*)&RAM[addr&0x07FF]);
} else if( addr < 0x8000 ) {
// Others
return (WORD)nes->Read(addr)+(WORD)nes->Read(addr+1)*0x100;
}
// Quick bank read
#if 0
WORD ret;
ret = (WORD)CPU_MEM_BANK[(addr+0)>>13][(addr+0)&0x1FFF];
ret |= (WORD)CPU_MEM_BANK[(addr+1)>>13][(addr+1)&0x1FFF]<<8;
return ret;
#else
return *((WORD*)&CPU_MEM_BANK[addr>>13][addr&0x1FFF]);
#endif
}
// 儊儌儕儔僀僩
inline void CPU::WR6502( WORD addr, BYTE data )
{
if( addr < 0x2000 ) {
// RAM (Mirror $0800, $1000, $1800)
RAM[addr&0x07FF] = data;
} else {
// Others
nes->Write( addr, data );
}
}
//
// 儕僙僢僩
//
void CPU::Reset()
{
apu = nes->apu;
mapper = nes->mapper;
R.A = 0x00;
R.X = 0x00;
R.Y = 0x00;
R.S = 0xFF;
R.P = Z_FLAG|R_FLAG;
R.PC = RD6502W(RES_VECTOR);
R.INT_pending = 0;
TOTAL_cycles = 0;
DMA_cycles = 0;
// STACK quick access
STACK = &RAM[0x0100];
// Zero/Negative FLAG
ZN_Table[0] = Z_FLAG;
for( INT i = 1; i < 256; i++ )
ZN_Table[i] = (i & 0x80)?N_FLAG:0;
}
INT CPU::GetDmaCycles()
{
return DMA_cycles;
}
void CPU::SetDmaCycles( INT cycles )
{
DMA_cycles = cycles;
}
INT CPU::GetTotalCycles()
{
return TOTAL_cycles;
}
void CPU::SetTotalCycles( INT cycles )
{
TOTAL_cycles = cycles;
}
//
// DMA儁儞僨傿儞僌僒僀僋儖愝掕
//
void CPU::DMA( INT cycles )
{
DMA_cycles += cycles;
}
//
// 妱傝崬傒
//
void CPU::NMI()
{
R.INT_pending |= NMI_FLAG;
}
void CPU::SetIRQ( BYTE mask )
{
R.INT_pending |= mask;
}
void CPU::ClrIRQ( BYTE mask )
{
R.INT_pending &= ~mask;
}
//
// 柦椷幚峴
//
INT CPU::EXEC( INT request_cycles )
{
BYTE opcode; // 僆儁僐乕僪
INT OLD_cycles = TOTAL_cycles;
INT exec_cycles;
BYTE nmi_request, irq_request;
BOOL bClockProcess = m_bClockProcess;
// TEMP
register WORD EA;
register WORD ET;
register WORD WT;
register BYTE DT;
while( request_cycles > 0 ) {
exec_cycles = 0;
if( DMA_cycles ) {
if( request_cycles <= DMA_cycles ) {
DMA_cycles -= request_cycles;
TOTAL_cycles += request_cycles;
// 僋儘僢僋摨婜張棟
mapper->Clock( request_cycles );
#if DPCM_SYNCCLOCK
apu->SyncDPCM( request_cycles );
#endif
if( bClockProcess ) {
nes->Clock( request_cycles );
}
goto _execute_exit;
} else {
exec_cycles += DMA_cycles;
request_cycles -= DMA_cycles;
DMA_cycles = 0;
}
}
nmi_request = irq_request = 0;
opcode = OP6502( R.PC++ );
if( R.INT_pending ) {
if( R.INT_pending & NMI_FLAG ) {
nmi_request = 0xFF;
R.INT_pending &= ~NMI_FLAG;
} else
if( R.INT_pending & IRQ_MASK ) {
R.INT_pending &= ~IRQ_TRIGGER2;
if( !(R.P & I_FLAG) && opcode != 0x40 ) {
irq_request = 0xFF;
R.INT_pending &= ~IRQ_TRIGGER;
}
}
}
switch( opcode ) {
case 0x69: // ADC #$??
MR_IM(); ADC();
ADD_CYCLE(2);
break;
case 0x65: // ADC $??
MR_ZP(); ADC();
ADD_CYCLE(3);
break;
case 0x75: // ADC $??,X
MR_ZX(); ADC();
ADD_CYCLE(4);
break;
case 0x6D: // ADC $????
MR_AB(); ADC();
ADD_CYCLE(4);
break;
case 0x7D: // ADC $????,X
MR_AX(); ADC(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x79: // ADC $????,Y
MR_AY(); ADC(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x61: // ADC ($??,X)
MR_IX(); ADC();
ADD_CYCLE(6);
break;
case 0x71: // ADC ($??),Y
MR_IY(); ADC(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0xE9: // SBC #$??
MR_IM(); SBC();
ADD_CYCLE(2);
break;
case 0xE5: // SBC $??
MR_ZP(); SBC();
ADD_CYCLE(3);
break;
case 0xF5: // SBC $??,X
MR_ZX(); SBC();
ADD_CYCLE(4);
break;
case 0xED: // SBC $????
MR_AB(); SBC();
ADD_CYCLE(4);
break;
case 0xFD: // SBC $????,X
MR_AX(); SBC(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0xF9: // SBC $????,Y
MR_AY(); SBC(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0xE1: // SBC ($??,X)
MR_IX(); SBC();
ADD_CYCLE(6);
break;
case 0xF1: // SBC ($??),Y
MR_IY(); SBC(); CHECK_EA();
ADD_CYCLE(5);
break;
case 0xC6: // DEC $??
MR_ZP(); DEC(); MW_ZP();
ADD_CYCLE(5);
break;
case 0xD6: // DEC $??,X
MR_ZX(); DEC(); MW_ZP();
ADD_CYCLE(6);
break;
case 0xCE: // DEC $????
MR_AB(); DEC(); MW_EA();
ADD_CYCLE(6);
break;
case 0xDE: // DEC $????,X
MR_AX(); DEC(); MW_EA();
ADD_CYCLE(7);
break;
case 0xCA: // DEX
DEX();
ADD_CYCLE(2);
break;
case 0x88: // DEY
DEY();
ADD_CYCLE(2);
break;
case 0xE6: // INC $??
MR_ZP(); INC(); MW_ZP();
ADD_CYCLE(5);
break;
case 0xF6: // INC $??,X
MR_ZX(); INC(); MW_ZP();
ADD_CYCLE(6);
break;
case 0xEE: // INC $????
MR_AB(); INC(); MW_EA();
ADD_CYCLE(6);
break;
case 0xFE: // INC $????,X
MR_AX(); INC(); MW_EA();
ADD_CYCLE(7);
break;
case 0xE8: // INX
INX();
ADD_CYCLE(2);
break;
case 0xC8: // INY
INY();
ADD_CYCLE(2);
break;
case 0x29: // AND #$??
MR_IM(); AND();
ADD_CYCLE(2);
break;
case 0x25: // AND $??
MR_ZP(); AND();
ADD_CYCLE(3);
break;
case 0x35: // AND $??,X
MR_ZX(); AND();
ADD_CYCLE(4);
break;
case 0x2D: // AND $????
MR_AB(); AND();
ADD_CYCLE(4);
break;
case 0x3D: // AND $????,X
MR_AX(); AND(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x39: // AND $????,Y
MR_AY(); AND(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x21: // AND ($??,X)
MR_IX(); AND();
ADD_CYCLE(6);
break;
case 0x31: // AND ($??),Y
MR_IY(); AND(); CHECK_EA();
ADD_CYCLE(5);
break;
case 0x0A: // ASL A
ASL_A();
ADD_CYCLE(2);
break;
case 0x06: // ASL $??
MR_ZP(); ASL(); MW_ZP();
ADD_CYCLE(5);
break;
case 0x16: // ASL $??,X
MR_ZX(); ASL(); MW_ZP();
ADD_CYCLE(6);
break;
case 0x0E: // ASL $????
MR_AB(); ASL(); MW_EA();
ADD_CYCLE(6);
break;
case 0x1E: // ASL $????,X
MR_AX(); ASL(); MW_EA();
ADD_CYCLE(7);
break;
case 0x24: // BIT $??
MR_ZP(); BIT();
ADD_CYCLE(3);
break;
case 0x2C: // BIT $????
MR_AB(); BIT();
ADD_CYCLE(4);
break;
case 0x49: // EOR #$??
MR_IM(); EOR();
ADD_CYCLE(2);
break;
case 0x45: // EOR $??
MR_ZP(); EOR();
ADD_CYCLE(3);
break;
case 0x55: // EOR $??,X
MR_ZX(); EOR();
ADD_CYCLE(4);
break;
case 0x4D: // EOR $????
MR_AB(); EOR();
ADD_CYCLE(4);
break;
case 0x5D: // EOR $????,X
MR_AX(); EOR(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x59: // EOR $????,Y
MR_AY(); EOR(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x41: // EOR ($??,X)
MR_IX(); EOR();
ADD_CYCLE(6);
break;
case 0x51: // EOR ($??),Y
MR_IY(); EOR(); CHECK_EA();
ADD_CYCLE(5);
break;
case 0x4A: // LSR A
LSR_A();
ADD_CYCLE(2);
break;
case 0x46: // LSR $??
MR_ZP(); LSR(); MW_ZP();
ADD_CYCLE(5);
break;
case 0x56: // LSR $??,X
MR_ZX(); LSR(); MW_ZP();
ADD_CYCLE(6);
break;
case 0x4E: // LSR $????
MR_AB(); LSR(); MW_EA();
ADD_CYCLE(6);
break;
case 0x5E: // LSR $????,X
MR_AX(); LSR(); MW_EA();
ADD_CYCLE(7);
break;
case 0x09: // ORA #$??
MR_IM(); ORA();
ADD_CYCLE(2);
break;
case 0x05: // ORA $??
MR_ZP(); ORA();
ADD_CYCLE(3);
break;
case 0x15: // ORA $??,X
MR_ZX(); ORA();
ADD_CYCLE(4);
break;
case 0x0D: // ORA $????
MR_AB(); ORA();
ADD_CYCLE(4);
break;
case 0x1D: // ORA $????,X
MR_AX(); ORA(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x19: // ORA $????,Y
MR_AY(); ORA(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x01: // ORA ($??,X)
MR_IX(); ORA();
ADD_CYCLE(6);
break;
case 0x11: // ORA ($??),Y
MR_IY(); ORA(); CHECK_EA();
ADD_CYCLE(5);
break;
case 0x2A: // ROL A
ROL_A();
ADD_CYCLE(2);
break;
case 0x26: // ROL $??
MR_ZP(); ROL(); MW_ZP();
ADD_CYCLE(5);
break;
case 0x36: // ROL $??,X
MR_ZX(); ROL(); MW_ZP();
ADD_CYCLE(6);
break;
case 0x2E: // ROL $????
MR_AB(); ROL(); MW_EA();
ADD_CYCLE(6);
break;
case 0x3E: // ROL $????,X
MR_AX(); ROL(); MW_EA();
ADD_CYCLE(7);
break;
case 0x6A: // ROR A
ROR_A();
ADD_CYCLE(2);
break;
case 0x66: // ROR $??
MR_ZP(); ROR(); MW_ZP();
ADD_CYCLE(5);
break;
case 0x76: // ROR $??,X
MR_ZX(); ROR(); MW_ZP();
ADD_CYCLE(6);
break;
case 0x6E: // ROR $????
MR_AB(); ROR(); MW_EA();
ADD_CYCLE(6);
break;
case 0x7E: // ROR $????,X
MR_AX(); ROR(); MW_EA();
ADD_CYCLE(7);
break;
case 0xA9: // LDA #$??
MR_IM(); LDA();
ADD_CYCLE(2);
break;
case 0xA5: // LDA $??
MR_ZP(); LDA();
ADD_CYCLE(3);
break;
case 0xB5: // LDA $??,X
MR_ZX(); LDA();
ADD_CYCLE(4);
break;
case 0xAD: // LDA $????
MR_AB(); LDA();
ADD_CYCLE(4);
break;
case 0xBD: // LDA $????,X
MR_AX(); LDA(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0xB9: // LDA $????,Y
MR_AY(); LDA(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0xA1: // LDA ($??,X)
MR_IX(); LDA();
ADD_CYCLE(6);
break;
case 0xB1: // LDA ($??),Y
MR_IY(); LDA(); CHECK_EA();
ADD_CYCLE(5);
break;
case 0xA2: // LDX #$??
MR_IM(); LDX();
ADD_CYCLE(2);
break;
case 0xA6: // LDX $??
MR_ZP(); LDX();
ADD_CYCLE(3);
break;
case 0xB6: // LDX $??,Y
MR_ZY(); LDX();
ADD_CYCLE(4);
break;
case 0xAE: // LDX $????
MR_AB(); LDX();
ADD_CYCLE(4);
break;
case 0xBE: // LDX $????,Y
MR_AY(); LDX(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0xA0: // LDY #$??
MR_IM(); LDY();
ADD_CYCLE(2);
break;
case 0xA4: // LDY $??
MR_ZP(); LDY();
ADD_CYCLE(3);
break;
case 0xB4: // LDY $??,X
MR_ZX(); LDY();
ADD_CYCLE(4);
break;
case 0xAC: // LDY $????
MR_AB(); LDY();
ADD_CYCLE(4);
break;
case 0xBC: // LDY $????,X
MR_AX(); LDY(); CHECK_EA();
ADD_CYCLE(4);
break;
case 0x85: // STA $??
EA_ZP(); STA(); MW_ZP();
ADD_CYCLE(3);
break;
case 0x95: // STA $??,X
EA_ZX(); STA(); MW_ZP();
ADD_CYCLE(4);
break;
case 0x8D: // STA $????
EA_AB(); STA(); MW_EA();
ADD_CYCLE(4);
break;
case 0x9D: // STA $????,X
EA_AX(); STA(); MW_EA();
ADD_CYCLE(5);
break;
case 0x99: // STA $????,Y
EA_AY(); STA(); MW_EA();
ADD_CYCLE(5);
break;
case 0x81: // STA ($??,X)
EA_IX(); STA(); MW_EA();
ADD_CYCLE(6);
break;
case 0x91: // STA ($??),Y
EA_IY(); STA(); MW_EA();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -