📄 nes6502.c
字号:
INLINE uint32 bank_readaddress(register uint32 address){ uint8 *x = nes6502_banks[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK); return (x[1] << 8) | x[0];}/* read a byte of 6502 memory */static uint8 mem_read(uint32 address){ /* TODO: following cases are N2A03-specific */ /* RAM */ if (address < 0x800) return ram[address]; /* always paged memory */// else if (address >= 0x6000) else if (address >= 0x8000) return bank_readbyte(address); /* check memory range handlers */ else { for (pmr = pmem_read; pmr->min_range != 0xFFFFFFFF; pmr++) { if ((address >= pmr->min_range) && (address <= pmr->max_range)) return pmr->read_func(address); } } /* return paged memory */ return bank_readbyte(address);}/* write a byte of data to 6502 memory */static void mem_write(uint32 address, uint8 value){ /* RAM */ if (address < 0x800) { ram[address] = value; return; } /* check memory range handlers */ else { for (pmw = pmem_write; pmw->min_range != 0xFFFFFFFF; pmw++) { if ((address >= pmw->min_range) && (address <= pmw->max_range)) { pmw->write_func(address, value); return; } } } /* write to paged memory */ bank_writebyte(address, value);}/* set the current context */void nes6502_setcontext(nes6502_context *cpu){ int loop; ASSERT(cpu); /* Set the page pointers */ for (loop = 0; loop < NES6502_NUMBANKS; loop++) nes6502_banks[loop] = cpu->mem_page[loop]; ram = nes6502_banks[0]; /* quicker zero-page/RAM references */ stack_page = ram + STACK_OFFSET; pmem_read = cpu->read_handler; pmem_write = cpu->write_handler; reg_PC = cpu->pc_reg; reg_A = cpu->a_reg; reg_P = cpu->p_reg; reg_X = cpu->x_reg; reg_Y = cpu->y_reg; reg_S = cpu->s_reg; int_pending = cpu->int_pending; dma_cycles = cpu->dma_cycles;}/* get the current context */void nes6502_getcontext(nes6502_context *cpu){ int loop; /* Set the page pointers */ for (loop = 0; loop < NES6502_NUMBANKS; loop++) cpu->mem_page[loop] = nes6502_banks[loop]; cpu->read_handler = pmem_read; cpu->write_handler = pmem_write; cpu->pc_reg = reg_PC; cpu->a_reg = reg_A; cpu->p_reg = reg_P; cpu->x_reg = reg_X; cpu->y_reg = reg_Y; cpu->s_reg = reg_S; cpu->int_pending = int_pending; cpu->dma_cycles = dma_cycles;}/* DMA a byte of data from ROM */uint8 nes6502_getbyte(uint32 address){ return bank_readbyte(address);}/* get number of elapsed cycles */uint32 nes6502_getcycles(boolean reset_flag){ uint32 cycles = total_cycles; if (reset_flag) total_cycles = 0; return cycles;}/* Execute instructions until count expires**** Returns the number of cycles *actually* executed** (note that this can be from 0-6 cycles more than you wanted)*/int nes6502_execute(int remaining_cycles){ int instruction_cycles, old_cycles = total_cycles; uint32 temp, addr; /* for macros */ uint32 PC; uint8 A, X, Y, P, S; uint8 opcode, data; uint8 btemp, baddr; /* for macros */ GET_GLOBAL_REGS(); /* Continue until we run out of cycles */ while (remaining_cycles > 0) { instruction_cycles = 0; /* check for DMA cycle burning */ if (dma_cycles) { if (remaining_cycles <= dma_cycles) { dma_cycles -= remaining_cycles; total_cycles += remaining_cycles; goto _execute_done; } else { remaining_cycles -= dma_cycles; total_cycles += dma_cycles; dma_cycles = 0; } } if (int_pending) { /* NMI has highest priority */ if (int_pending & NMI_MASK) { NMI(); } /* IRQ has lowest priority */ else /* if (int_pending & IRQ_MASK) */ { if (IS_FLAG_CLEAR(I_FLAG)) IRQ(); } } /* Fetch instruction */ //nes6502_disasm(PC, P, A, X, Y, S); opcode = bank_readbyte(PC++); /* Execute instruction */ switch (opcode) { case 0x00: /* BRK */ BRK(); break; case 0x01: /* ORA ($nn,X) */ ORA(6, INDIR_X_BYTE); break; /* JAM */ case 0x02: /* JAM */ case 0x12: /* JAM */ case 0x22: /* JAM */ case 0x32: /* JAM */ case 0x42: /* JAM */ case 0x52: /* JAM */ case 0x62: /* JAM */ case 0x72: /* JAM */ case 0x92: /* JAM */ case 0xB2: /* JAM */ case 0xD2: /* JAM */ case 0xF2: /* JAM */ JAM(); /* kill switch for CPU emulation */ goto _execute_done; case 0x03: /* SLO ($nn,X) */ SLO(8, INDIR_X, mem_write, addr); break; case 0x04: /* NOP $nn */ case 0x44: /* NOP $nn */ case 0x64: /* NOP $nn */ DOP(3); break; case 0x05: /* ORA $nn */ ORA(3, ZERO_PAGE_BYTE); break; case 0x06: /* ASL $nn */ ASL(5, ZERO_PAGE, ZP_WRITE, baddr); break; case 0x07: /* SLO $nn */ SLO(5, ZERO_PAGE, ZP_WRITE, baddr); break; case 0x08: /* PHP */ PHP(); break; case 0x09: /* ORA #$nn */ ORA(2, IMMEDIATE_BYTE); break; case 0x0A: /* ASL A */ ASL_A(); break; case 0x0B: /* ANC #$nn */ ANC(2, IMMEDIATE_BYTE); break; case 0x0C: /* NOP $nnnn */ TOP(); break; case 0x0D: /* ORA $nnnn */ ORA(4, ABSOLUTE_BYTE); break; case 0x0E: /* ASL $nnnn */ ASL(6, ABSOLUTE, mem_write, addr); break; case 0x0F: /* SLO $nnnn */ SLO(6, ABSOLUTE, mem_write, addr); break; case 0x10: /* BPL $nnnn */ BPL(); break; case 0x11: /* ORA ($nn),Y */ ORA(5, INDIR_Y_BYTE); break; case 0x13: /* SLO ($nn),Y */ SLO(8, INDIR_Y, mem_write, addr); break; case 0x14: /* NOP $nn,X */ case 0x34: /* NOP */ case 0x54: /* NOP $nn,X */ case 0x74: /* NOP $nn,X */ case 0xD4: /* NOP $nn,X */ case 0xF4: /* NOP ($nn,X) */ DOP(4); break; case 0x15: /* ORA $nn,X */ ORA(4, ZP_IND_X_BYTE); break; case 0x16: /* ASL $nn,X */ ASL(6, ZP_IND_X, ZP_WRITE, baddr); break; case 0x17: /* SLO $nn,X */ SLO(6, ZP_IND_X, ZP_WRITE, baddr); break; case 0x18: /* CLC */ CLC(); break; case 0x19: /* ORA $nnnn,Y */ ORA(4, ABS_IND_Y_BYTE); break; case 0x1A: /* NOP */ case 0x3A: /* NOP */ case 0x5A: /* NOP */ case 0x7A: /* NOP */ case 0xDA: /* NOP */ case 0xFA: /* NOP */ NOP(); break; case 0x1B: /* SLO $nnnn,Y */ SLO(7, ABS_IND_Y, mem_write, addr); break; case 0x1C: /* NOP $nnnn,X */ case 0x3C: /* NOP $nnnn,X */ case 0x5C: /* NOP $nnnn,X */ case 0x7C: /* NOP $nnnn,X */ case 0xDC: /* NOP $nnnn,X */ case 0xFC: /* NOP $nnnn,X */ TOP(); break; case 0x1D: /* ORA $nnnn,X */ ORA(4, ABS_IND_X_BYTE); break; case 0x1E: /* ASL $nnnn,X */ ASL(7, ABS_IND_X, mem_write, addr); break; case 0x1F: /* SLO $nnnn,X */ SLO(7, ABS_IND_X, mem_write, addr); break; case 0x20: /* JSR $nnnn */ JSR(); break; case 0x21: /* AND ($nn,X) */ AND(6, INDIR_X_BYTE); break; case 0x23: /* RLA ($nn,X) */ RLA(8, INDIR_X, mem_write, addr); break; case 0x24: /* BIT $nn */ BIT(3, ZERO_PAGE_BYTE); break; case 0x25: /* AND $nn */ AND(3, ZERO_PAGE_BYTE); break; case 0x26: /* ROL $nn */ ROL(5, ZERO_PAGE, ZP_WRITE, baddr); break; case 0x27: /* RLA $nn */ RLA(5, ZERO_PAGE, ZP_WRITE, baddr); break; case 0x28: /* PLP */ PLP(); break; case 0x29: /* AND #$nn */ AND(2, IMMEDIATE_BYTE); break; case 0x2A: /* ROL A */ ROL_A(); break; case 0x2B: /* ANC #$nn */ ANC(2, IMMEDIATE_BYTE); break; case 0x2C: /* BIT $nnnn */ BIT(4, ABSOLUTE_BYTE); break; case 0x2D: /* AND $nnnn */ AND(4, ABSOLUTE_BYTE); break; case 0x2E: /* ROL $nnnn */ ROL(6, ABSOLUTE, mem_write, addr); break; case 0x2F: /* RLA $nnnn */ RLA(6, ABSOLUTE, mem_write, addr); break; case 0x30: /* BMI $nnnn */ BMI(); break; case 0x31: /* AND ($nn),Y */ AND(5, INDIR_Y_BYTE); break; case 0x33: /* RLA ($nn),Y */ RLA(8, INDIR_Y, mem_write, addr); break; case 0x35: /* AND $nn,X */ AND(4, ZP_IND_X_BYTE); break; case 0x36: /* ROL $nn,X */ ROL(6, ZP_IND_X, ZP_WRITE, baddr); break; case 0x37: /* RLA $nn,X */ RLA(6, ZP_IND_X, ZP_WRITE, baddr); break; case 0x38: /* SEC */ SEC(); break; case 0x39: /* AND $nnnn,Y */ AND(4, ABS_IND_Y_BYTE); break; case 0x3B: /* RLA $nnnn,Y */ RLA(7, ABS_IND_Y, mem_write, addr); break; case 0x3D: /* AND $nnnn,X */ AND(4, ABS_IND_X_BYTE); break; case 0x3E: /* ROL $nnnn,X */ ROL(7, ABS_IND_X, mem_write, addr); break; case 0x3F: /* RLA $nnnn,X */ RLA(7, ABS_IND_X, mem_write, addr); break; case 0x40: /* RTI */ RTI(); break; case 0x41: /* EOR ($nn,X) */ EOR(6, INDIR_X_BYTE); break; case 0x43: /* SRE ($nn,X) */ SRE(8, INDIR_X, mem_write, addr); break; case 0x45: /* EOR $nn */ EOR(3, ZERO_PAGE_BYTE); break; case 0x46: /* LSR $nn */ LSR(5, ZERO_PAGE, ZP_WRITE, baddr); break; case 0x47: /* SRE $nn */ SRE(5, ZERO_PAGE, ZP_WRITE, baddr); break; case 0x48: /* PHA */ PHA(); break; case 0x49: /* EOR #$nn */ EOR(2, IMMEDIATE_BYTE); break; case 0x4A: /* LSR A */ LSR_A(); break; case 0x4B: /* ASR #$nn */ ASR(2, IMMEDIATE_BYTE); break; case 0x4C: /* JMP $nnnn */ JMP_ABSOLUTE(); break; case 0x4D: /* EOR $nnnn */ EOR(4, ABSOLUTE_BYTE); break; case 0x4E: /* LSR $nnnn */ LSR(6, ABSOLUTE, mem_write, addr); break; case 0x4F: /* SRE $nnnn */ SRE(6, ABSOLUTE, mem_write, addr); break; case 0x50: /* BVC $nnnn */ BVC(); break; case 0x51: /* EOR ($nn),Y */ EOR(5, INDIR_Y_BYTE); break; case 0x53: /* SRE ($nn),Y */ SRE(8, INDIR_Y, mem_write, addr); break; case 0x55: /* EOR $nn,X */ EOR(4, ZP_IND_X_BYTE); break; case 0x56: /* LSR $nn,X */ LSR(6, ZP_IND_X, ZP_WRITE, baddr); break; case 0x57: /* SRE $nn,X */ SRE(6, ZP_IND_X, ZP_WRITE, baddr); break; case 0x58: /* CLI */ CLI(); break; case 0x59: /* EOR $nnnn,Y */ EOR(4, ABS_IND_Y_BYTE); break; case 0x5B: /* SRE $nnnn,Y */ SRE(7, ABS_IND_Y, mem_write, addr); break; case 0x5D: /* EOR $nnnn,X */ EOR(4, ABS_IND_X_BYTE); break; case 0x5E: /* LSR $nnnn,X */ LSR(7, ABS_IND_X, mem_write, addr); break; case 0x5F: /* SRE $nnnn,X */ SRE(7, ABS_IND_X, mem_write, addr); break; case 0x60: /* RTS */ RTS(); break; case 0x61: /* ADC ($nn,X) */ ADC(6, INDIR_X_BYTE); break; case 0x63: /* RRA ($nn,X) */ RRA(8, INDIR_X, mem_write, addr); break; case 0x65: /* ADC $nn */ ADC(3, ZERO_PAGE_BYTE); break; case 0x66: /* ROR $nn */ ROR(5, ZERO_PAGE, ZP_WRITE, baddr); break; case 0x67: /* RRA $nn */ RRA(5, ZERO_PAGE, ZP_WRITE, baddr); break; case 0x68: /* PLA */ PLA(); break; case 0x69: /* ADC #$nn */ ADC(2, IMMEDIATE_BYTE); break; case 0x6A: /* ROR A */ ROR_A(); break; case 0x6B: /* ARR #$nn */ ARR(2, IMMEDIATE_BYTE); break; case 0x6C: /* JMP ($nnnn) */ JMP_INDIRECT(); break; case 0x6D: /* ADC $nnnn */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -