📄 nes6502.c
字号:
/* undocumented */#define ISB(cycles, read_func, write_func, addr) \{ \ read_func(addr, data); \ data++; \ write_func(addr, data); \ SBC(cycles, NO_READ); \}#ifdef NES6502_TESTOPS#define JAM() \{ \ cpu_Jam(); \}#elif defined(NSF_PLAYER)#define JAM() \{ \}#else#define JAM() \{ \ char jambuf[20]; \ sprintf(jambuf, "JAM: PC=$%04X", PC); \ ASSERT_MSG(jambuf); \ ADD_CYCLES(2); \}#endif /* NES6502_TESTOPS */#define JMP_INDIRECT() \{ \ temp = bank_readaddress(PC); \ /* bug in crossing page boundaries */ \ if (0xFF == (uint8) temp) \ PC = (bank_readbyte(temp & ~0xFF) << 8) | bank_readbyte(temp); \ else \ JUMP(temp); \ ADD_CYCLES(5); \}#define JMP_ABSOLUTE() \{ \ JUMP(PC); \ ADD_CYCLES(3); \}#define JSR() \{ \ PC++; \ PUSH(PC >> 8); \ PUSH(PC & 0xFF); \ JUMP(PC - 1); \ ADD_CYCLES(6); \}/* undocumented */#define LAS(cycles, read_func) \{ \ read_func(data); \ A = X = S = (S & data); \ SET_NZ_FLAGS(A); \ ADD_CYCLES(cycles); \}/* undocumented */#define LAX(cycles, read_func) \{ \ read_func(A); \ X = A; \ SET_NZ_FLAGS(A); \ ADD_CYCLES(cycles); \}#define LDA(cycles, read_func) \{ \ read_func(A); \ SET_NZ_FLAGS(A); \ ADD_CYCLES(cycles); \}#define LDX(cycles, read_func) \{ \ read_func(X); \ SET_NZ_FLAGS(X);\ ADD_CYCLES(cycles); \}#define LDY(cycles, read_func) \{ \ read_func(Y); \ SET_NZ_FLAGS(Y);\ ADD_CYCLES(cycles); \}#define LSR(cycles, read_func, write_func, addr) \{ \ read_func(addr, data); \ TEST_AND_FLAG(data & 0x01, C_FLAG); \ data >>= 1; \ write_func(addr, data); \ SET_NZ_FLAGS(data); \ ADD_CYCLES(cycles); \}#define LSR_A() \{ \ TEST_AND_FLAG(A & 0x01, C_FLAG); \ A >>= 1; \ SET_NZ_FLAGS(A); \ ADD_CYCLES(2); \}/* undocumented */#define LXA(cycles, read_func) \{ \ read_func(data); \ A = X = ((A | 0xEE) & data); \ SET_NZ_FLAGS(A); \ ADD_CYCLES(cycles); \}#define NOP() \{ \ ADD_CYCLES(2); \}#define ORA(cycles, read_func) \{ \ read_func(data); \ A |= data; \ SET_NZ_FLAGS(A);\ ADD_CYCLES(cycles); \}#define PHA() \{ \ PUSH(A); \ ADD_CYCLES(3); \}#define PHP() \{ \ /* B flag is pushed on stack as well */ \ PUSH((P | B_FLAG)); \ ADD_CYCLES(3); \}#define PLA() \{ \ A = PULL(); \ SET_NZ_FLAGS(A); \ ADD_CYCLES(4); \}#define PLP() \{ \ P = PULL(); \ SET_FLAG(R_FLAG); /* ensure reserved flag is set */ \ ADD_CYCLES(4); \}/* undocumented */#define RLA(cycles, read_func, write_func, addr) \{ \ read_func(addr, data); \ if (P & C_FLAG) \ { \ TEST_AND_FLAG(data & 0x80, C_FLAG); \ data = (data << 1) | 1; \ } \ else \ { \ TEST_AND_FLAG(data & 0x80, C_FLAG); \ data <<= 1; \ } \ write_func(addr, data); \ A &= data; \ SET_NZ_FLAGS(A); \ ADD_CYCLES(cycles); \}/* 9-bit rotation (carry flag used for rollover) */#define ROL(cycles, read_func, write_func, addr) \{ \ read_func(addr, data); \ if (P & C_FLAG) \ { \ TEST_AND_FLAG(data & 0x80, C_FLAG); \ data = (data << 1) | 1; \ } \ else \ { \ TEST_AND_FLAG(data & 0x80, C_FLAG); \ data <<= 1; \ } \ write_func(addr, data); \ SET_NZ_FLAGS(data); \ ADD_CYCLES(cycles); \}#define ROL_A() \{ \ if (P & C_FLAG) \ { \ TEST_AND_FLAG(A & 0x80, C_FLAG); \ A = (A << 1) | 1; \ } \ else \ { \ TEST_AND_FLAG(A & 0x80, C_FLAG); \ A <<= 1; \ } \ SET_NZ_FLAGS(A); \ ADD_CYCLES(2); \}#define ROR(cycles, read_func, write_func, addr) \{ \ read_func(addr, data); \ if (P & C_FLAG) \ { \ TEST_AND_FLAG(data & 1, C_FLAG); \ data = (data >> 1) | 0x80; \ } \ else \ { \ TEST_AND_FLAG(data & 1, C_FLAG); \ data >>= 1; \ } \ write_func(addr, data); \ SET_NZ_FLAGS(data); \ ADD_CYCLES(cycles); \}#define ROR_A() \{ \ if (P & C_FLAG) \ { \ TEST_AND_FLAG(A & 1, C_FLAG); \ A = (A >> 1) | 0x80; \ } \ else \ { \ TEST_AND_FLAG(A & 1, C_FLAG); \ A >>= 1; \ } \ SET_NZ_FLAGS(A); \ ADD_CYCLES(2); \}/* undocumented */#define RRA(cycles, read_func, write_func, addr) \{ \ read_func(addr, data); \ if (P & C_FLAG) \ { \ TEST_AND_FLAG(data & 1, C_FLAG); \ data = (data >> 1) | 0x80; \ } \ else \ { \ TEST_AND_FLAG(data & 1, C_FLAG); \ data >>= 1; \ } \ write_func(addr, data); \ ADC(cycles, NO_READ); \}#define RTI() \{ \ P = PULL(); \ SET_FLAG(R_FLAG); /* ensure reserved flag is set */ \ PC = PULL(); \ PC |= PULL() << 8; \ ADD_CYCLES(6); \}#define RTS() \{ \ PC = PULL(); \ PC = (PC | (PULL() << 8)) + 1; \ ADD_CYCLES(6); \}/* undocumented */#define SAX(cycles, read_func, write_func, addr) \{ \ read_func(addr); \ data = A & X; \ write_func(addr, data); \ ADD_CYCLES(cycles); \}/* Warning! NES CPU has no decimal mode, so by default this does no BCD! */#ifdef NES6502_DECIMAL#define SBC(cycles, read_func) \{ \ read_func(data); \ /* NOT(C) is considered borrow */ \ temp = A - data - ((P & C_FLAG) ^ C_FLAG); \ if (P & D_FLAG) \ { \ uint8 al, ah; \ al = (A & 0x0F) - (data & 0x0F) - ((P & C_FLAG) ^ C_FLAG); \ ah = (A >> 4) - (data >> 4); \ if (al & 0x10) \ { \ al -= 6; \ ah--; \ } \ if (ah & 0x10) \ ah -= 6; \ TEST_AND_FLAG(temp < 0x100, C_FLAG); \ TEST_AND_FLAG(((A ^ temp) & 0x80) && ((A ^ data) & 0x80), V_FLAG); \ SET_NZ_FLAGS(temp & 0xFF); \ A = (ah << 4) | (al & 0x0F); \ } \ else \ { \ TEST_AND_FLAG(((A ^ temp) & 0x80) && ((A ^ data) & 0x80), V_FLAG); \ TEST_AND_FLAG(temp < 0x100, C_FLAG); \ A = (uint8) temp; \ SET_NZ_FLAGS(A & 0xFF); \ } \ ADD_CYCLES(cycles); \}#else#define SBC(cycles, read_func) \{ \ read_func(data); \ temp = A - data - ((P & C_FLAG) ^ C_FLAG); \ TEST_AND_FLAG(((A ^ data) & (A ^ temp) & 0x80), V_FLAG); \ TEST_AND_FLAG(temp < 0x100, C_FLAG); \ A = (uint8) temp; \ SET_NZ_FLAGS(A); \ ADD_CYCLES(cycles); \}#endif /* NES6502_DECIMAL *//* undocumented */#define SBX(cycles, read_func) \{ \ read_func(data); \ temp = (A & X) - data; \ TEST_AND_FLAG(temp < 0x100, C_FLAG); \ X = temp & 0xFF; \ SET_NZ_FLAGS(X); \ ADD_CYCLES(cycles); \}#define SEC() \{ \ SET_FLAG(C_FLAG); \ ADD_CYCLES(2); \}#define SED() \{ \ SET_FLAG(D_FLAG); \ ADD_CYCLES(2); \}#define SEI() \{ \ SET_FLAG(I_FLAG); \ ADD_CYCLES(2); \}/* undocumented */#define SHA(cycles, read_func, write_func, addr) \{ \ read_func(addr); \ data = A & X & ((uint8) ((addr >> 8) + 1)); \ write_func(addr, data); \ ADD_CYCLES(cycles); \}/* undocumented */#define SHS(cycles, read_func, write_func, addr) \{ \ read_func(addr); \ S = A & X; \ data = S & ((uint8) ((addr >> 8) + 1)); \ write_func(addr, data); \ ADD_CYCLES(cycles); \}/* undocumented */#define SHX(cycles, read_func, write_func, addr) \{ \ read_func(addr); \ data = X & ((uint8) ((addr >> 8) + 1)); \ write_func(addr, data); \ ADD_CYCLES(cycles); \}/* undocumented */#define SHY(cycles, read_func, write_func, addr) \{ \ read_func(addr); \ data = Y & ((uint8) ((addr >> 8 ) + 1)); \ write_func(addr, data); \ ADD_CYCLES(cycles); \}/* undocumented */#define SLO(cycles, read_func, write_func, addr) \{ \ read_func(addr, data); \ TEST_AND_FLAG(data & 0x80, C_FLAG); \ data <<= 1; \ write_func(addr, data); \ A |= data; \ SET_NZ_FLAGS(A); \ ADD_CYCLES(cycles); \}/* unoffical */#define SRE(cycles, read_func, write_func, addr) \{ \ read_func(addr, data); \ TEST_AND_FLAG(data & 1, C_FLAG); \ data >>= 1; \ write_func(addr, data); \ A ^= data; \ SET_NZ_FLAGS(A); \ ADD_CYCLES(cycles); \}#define STA(cycles, read_func, write_func, addr) \{ \ read_func(addr); \ write_func(addr, A); \ ADD_CYCLES(cycles); \}#define STX(cycles, read_func, write_func, addr) \{ \ read_func(addr); \ write_func(addr, X); \ ADD_CYCLES(cycles); \}#define STY(cycles, read_func, write_func, addr) \{ \ read_func(addr); \ write_func(addr, Y); \ ADD_CYCLES(cycles); \}#define TAX() \{ \ X = A; \ SET_NZ_FLAGS(X);\ ADD_CYCLES(2); \}#define TAY() \{ \ Y = A; \ SET_NZ_FLAGS(Y);\ ADD_CYCLES(2); \}/* undocumented (triple-NOP) */#define TOP() \{ \ PC += 2; \ ADD_CYCLES(4); \}#define TSX() \{ \ X = S; \ SET_NZ_FLAGS(X);\ ADD_CYCLES(2); \}#define TXA() \{ \ A = X; \ SET_NZ_FLAGS(A);\ ADD_CYCLES(2); \}#define TXS() \{ \ S = X; \ ADD_CYCLES(2); \}#define TYA() \{ \ A = Y; \ SET_NZ_FLAGS(A); \ ADD_CYCLES(2); \}/*** Stack and data fetching macros*//* Set/clear/test bits in the flags register */#define SET_FLAG(mask) P |= (mask)#define CLEAR_FLAG(mask) P &= ~(mask)#define IS_FLAG_SET(mask) (P & (mask))#define IS_FLAG_CLEAR(mask) (0 == IS_FLAG_SET((mask)))#define TEST_AND_FLAG(test, mask) \{ \ if ((test)) \ SET_FLAG((mask)); \ else \ CLEAR_FLAG((mask)); \}/*** flag register helper macros*//* register push/pull */#define PUSH(value) stack_page[S--] = (uint8) (value)#define PULL() stack_page[++S]/* Sets the Z and N flags based on given data, taken from precomputed table */#define SET_NZ_FLAGS(value) P &= ~(N_FLAG | Z_FLAG); \ P |= flag_table[(value)]#define GET_GLOBAL_REGS() \{ \ PC = reg_PC; \ A = reg_A; \ X = reg_X; \ Y = reg_Y; \ P = reg_P; \ S = reg_S; \}#define SET_LOCAL_REGS() \{ \ reg_PC = PC; \ reg_A = A; \ reg_X = X; \ reg_Y = Y; \ reg_P = P; \ reg_S = S; \}/* static data */static nes6502_memread *pmem_read, *pmr;static nes6502_memwrite *pmem_write, *pmw;/* lookup table for N/Z flags */static uint8 flag_table[256];/* internal critical CPU vars */static uint32 reg_PC;static uint8 reg_A, reg_P, reg_X, reg_Y, reg_S;static uint8 int_pending;static int dma_cycles;/* execution cycle count (can be reset by user) */static uint32 total_cycles = 0;/* memory region pointers */static uint8 *nes6502_banks[NES6502_NUMBANKS];static uint8 *ram = NULL;static uint8 *stack_page = NULL;/*** Zero-page helper macros*/#define ZP_READ(addr) ram[(addr)]#define ZP_WRITE(addr, value) ram[(addr)] = (uint8) (value)INLINE uint8 bank_readbyte(register uint32 address){ ASSERT(nes6502_banks[address >> NES6502_BANKSHIFT]); return nes6502_banks[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK];}INLINE void bank_writebyte(register uint32 address, register uint8 value){ ASSERT(nes6502_banks[address >> NES6502_BANKSHIFT]); nes6502_banks[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK] = value;}INLINE uint32 zp_address(register uint8 address){ uint8 *x = ram + address; return (x[1] << 8) | x[0];}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -