⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nes6502.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 4 页
字号:
/*** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)****** This program is free software; you can redistribute it and/or** modify it under the terms of version 2 of the GNU Library General ** Public License as published by the Free Software Foundation.**** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU ** Library General Public License for more details.  To obtain a ** copy of the GNU Library General Public License, write to the Free ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.**** Any permitted reproduction of these routines, in whole or in part,** must bear this legend.****** nes6502.c**** NES custom 6502 (2A03) CPU implementation** $Id: nes6502.c,v 1.2 2003/01/09 19:50:03 jkeil Exp $*/#include "types.h"#include "nes6502.h"#include "dis6502.h"#include <stdio.h>#define  ADD_CYCLES(x)     instruction_cycles += (x)#define  INC_CYCLES()      instruction_cycles++//#define  ADD_CYCLES(x)  remaining_cycles -= (x)//#define  INC_CYCLES()   remaining_cycles--/*** Check to see if an index reg addition overflowed to next page*/#define CHECK_INDEX_OVERFLOW(addr, reg) \{ \   if ((uint8) (addr) < (reg)) \      INC_CYCLES(); \}/*** Addressing mode macros*/#define NO_READ(value)        /* empty */#define IMMEDIATE_BYTE(value) \{ \   value = bank_readbyte(PC++); \}#define ABSOLUTE_ADDR(address) \{ \   address = bank_readaddress(PC); \   PC += 2; \}#define ABSOLUTE(address, value) \{ \   ABSOLUTE_ADDR(address); \   value = mem_read(address); \}#define ABSOLUTE_BYTE(value) \{ \   ABSOLUTE(temp, value); \}#define ABS_IND_X_ADDR(address) \{ \   address = (bank_readaddress(PC) + X) & 0xFFFF; \   PC += 2; \   CHECK_INDEX_OVERFLOW(address, X); \}#define ABS_IND_X(address, value) \{ \   ABS_IND_X_ADDR(address); \   value = mem_read(address); \}#define ABS_IND_X_BYTE(value) \{ \   ABS_IND_X(temp, value); \}#define ABS_IND_Y_ADDR(address) \{ \   address = (bank_readaddress(PC) + Y) & 0xFFFF; \   PC += 2; \   CHECK_INDEX_OVERFLOW(address, Y); \}#define ABS_IND_Y(address, value) \{ \   ABS_IND_Y_ADDR(address); \   value = mem_read(address); \}#define ABS_IND_Y_BYTE(value) \{ \   ABS_IND_Y(temp, value); \}#define ZERO_PAGE_ADDR(address) \{ \   IMMEDIATE_BYTE(address); \}#define ZERO_PAGE(address, value) \{ \   ZERO_PAGE_ADDR(address); \   value = ZP_READ(address); \}#define ZERO_PAGE_BYTE(value) \{ \   ZERO_PAGE(btemp, value); \}/* Zero-page indexed Y doesn't really exist, just for LDX / STX */#define ZP_IND_X_ADDR(address) \{ \   address = bank_readbyte(PC++) + X; \}#define ZP_IND_X(bAddr, value) \{ \   ZP_IND_X_ADDR(bAddr); \   value = ZP_READ(bAddr); \}#define ZP_IND_X_BYTE(value) \{ \   ZP_IND_X(btemp, value); \}#define ZP_IND_Y_ADDR(address) \{ \   address = bank_readbyte(PC++) + Y; \}#define ZP_IND_Y(address, value) \{ \   ZP_IND_Y_ADDR(address); \   value = ZP_READ(address); \}#define ZP_IND_Y_BYTE(value) \{ \   ZP_IND_Y(btemp, value); \}  /*** For conditional jump relative instructions** (BCC, BCS, BEQ, BMI, BNE, BPL, BVC, BVS)*/#define RELATIVE_JUMP(cond) \{ \   if (cond) \   { \      IMMEDIATE_BYTE(btemp); \      if (((int8) btemp + (uint8) PC) & 0xFF00) \         ADD_CYCLES(4); \      else \         ADD_CYCLES(3); \      PC += ((int8) btemp); \   } \   else \   { \      PC++; \      ADD_CYCLES(2); \   } \}/*** This is actually indexed indirect, but I call it** indirect X to avoid confusion*/#define INDIR_X_ADDR(address) \{ \   btemp = bank_readbyte(PC++) + X; \   address = zp_address(btemp); \}#define INDIR_X(address, value) \{ \   INDIR_X_ADDR(address); \   value = mem_read(address); \} #define INDIR_X_BYTE(value) \{ \   INDIR_X(temp, value); \}/*** This is actually indirect indexed, but I call it** indirect y to avoid confusion*/#define INDIR_Y_ADDR(address) \{ \   IMMEDIATE_BYTE(btemp); \   address = (zp_address(btemp) + Y) & 0xFFFF; \   /* ???? */ \   CHECK_INDEX_OVERFLOW(address, Y); \}#define INDIR_Y(address, value) \{ \   INDIR_Y_ADDR(address); \   value = mem_read(address); \} #define INDIR_Y_BYTE(value) \{ \   /*IMMEDIATE_BYTE(btemp); \   temp = zp_address(btemp) + Y; \   CHECK_INDEX_OVERFLOW(temp, Y); \   value = mem_read(temp);*/ \   INDIR_Y(temp, value); \}#define  JUMP(address)  PC = bank_readaddress((address))/*** Interrupt macros*/#define NMI() \{ \   PUSH(PC >> 8); \   PUSH(PC & 0xFF); \   CLEAR_FLAG(B_FLAG); \   PUSH(P); \   SET_FLAG(I_FLAG); \   JUMP(NMI_VECTOR); \   int_pending &= ~NMI_MASK; \   ADD_CYCLES(INT_CYCLES); \}#define IRQ() \{ \   PUSH(PC >> 8); \   PUSH(PC & 0xFF); \   CLEAR_FLAG(B_FLAG); \   PUSH(P); \   SET_FLAG(I_FLAG); \   JUMP(IRQ_VECTOR); \   int_pending &= ~IRQ_MASK; \   ADD_CYCLES(INT_CYCLES); \}/*** Instruction macros*//* Warning! NES CPU has no decimal mode, so by default this does no BCD! */#ifdef NES6502_DECIMAL#define ADC(cycles, read_func) \{ \   read_func(data); \   if (P & D_FLAG) \   { \      temp = (A & 0x0F) + (data & 0x0F) + (P & C_FLAG); \      if (temp >= 10) \         temp = (temp - 10) | 0x10; \      temp += (A & 0xF0) + (data & 0xF0); \      TEST_AND_FLAG(0 == ((A + data + (P & C_FLAG)) & 0xFF), Z_FLAG); \      TEST_AND_FLAG(temp & 0x80, N_FLAG); \      TEST_AND_FLAG(((~(A ^ data)) & (A ^ temp) & 0x80), V_FLAG); \      if (temp > 0x9F) \         temp += 0x60; \      TEST_AND_FLAG(temp > 0xFF, C_FLAG); \      A = (uint8) temp; \   } \   else \   { \      temp = A + data + (P & C_FLAG); \      /* Set C on carry */ \      TEST_AND_FLAG(temp > 0xFF, C_FLAG); \      /* Set V on overflow */ \      TEST_AND_FLAG(((~(A ^ data)) & (A ^ temp) & 0x80), V_FLAG); \      A = (uint8) temp; \      SET_NZ_FLAGS(A); \   }\   ADD_CYCLES(cycles); \}#else#define ADC(cycles, read_func) \{ \   read_func(data); \   temp = A + data + (P & C_FLAG); \   /* Set C on carry */ \   TEST_AND_FLAG(temp > 0xFF, C_FLAG); \   /* Set V on overflow */ \   TEST_AND_FLAG(((~(A ^ data)) & (A ^ temp) & 0x80), V_FLAG); \   A = (uint8) temp; \   SET_NZ_FLAGS(A); \   ADD_CYCLES(cycles); \}#endif /* NES6502_DECIMAL *//* undocumented */#define ANC(cycles, read_func) \{ \   read_func(data); \   A &= data; \   SET_NZ_FLAGS(A); \   TEST_AND_FLAG(P & N_FLAG, C_FLAG); \   ADD_CYCLES(cycles); \}#define AND(cycles, read_func) \{ \   read_func(data); \   A &= data; \   SET_NZ_FLAGS(A); \   ADD_CYCLES(cycles); \}/* undocumented */#define ANE(cycles, read_func) \{ \   read_func(data); \   A = (A | 0xEE) & X & data; \   SET_NZ_FLAGS(A); \   ADD_CYCLES(cycles); \}/* undocumented */#ifdef NES6502_DECIMAL#define ARR(cycles, read_func) \{ \   read_func(data); \   data &= A; \   if (P & D_FLAG) \   { \      temp = (data >> 1) | ((P & C_FLAG) << 7); \      SET_NZ_FLAGS(temp); \      TEST_AND_FLAG((temp ^ data) & 0x40, V_FLAG); \      if (((data & 0x0F) + (data & 0x01)) > 5) \         temp = (temp & 0xF0) | ((temp + 0x6) & 0x0F); \      if (((data & 0xF0) + (data & 0x10)) > 0x50) \      { \         temp = (temp & 0x0F) | ((temp + 0x60) & 0xF0); \         SET_FLAG(C_FLAG); \      } \      else \         CLEAR_FLAG(C_FLAG); \      A = (uint8) temp; \   } \   else \   { \      A = (data >> 1) | ((P & C_FLAG) << 7); \      SET_NZ_FLAGS(A); \      TEST_AND_FLAG(A & 0x40, C_FLAG); \      TEST_AND_FLAG(((A >> 6) ^ (A >> 5)) & 1, V_FLAG); \   }\   ADD_CYCLES(cycles); \}#else#define ARR(cycles, read_func) \{ \   read_func(data); \   data &= A; \   A = (data >> 1) | ((P & C_FLAG) << 7); \   SET_NZ_FLAGS(A); \   TEST_AND_FLAG(A & 0x40, C_FLAG); \   TEST_AND_FLAG((A >> 6) ^ (A >> 5), V_FLAG); \   ADD_CYCLES(cycles); \}#endif /* NES6502_DECIMAL */#define ASL(cycles, read_func, write_func, addr) \{ \   read_func(addr, data); \   TEST_AND_FLAG(data & 0x80, C_FLAG); \   data <<= 1; \   write_func(addr, data); \   SET_NZ_FLAGS(data); \   ADD_CYCLES(cycles); \}#define ASL_A() \{ \   TEST_AND_FLAG(A & 0x80, C_FLAG); \   A <<= 1; \   SET_NZ_FLAGS(A); \   ADD_CYCLES(2); \}/* undocumented */#define ASR(cycles, read_func) \{ \   read_func(data); \   data &= A; \   TEST_AND_FLAG(data & 0x01, C_FLAG); \   A = data >> 1; \   SET_NZ_FLAGS(A); \   ADD_CYCLES(cycles); \}#define BCC() \{ \   RELATIVE_JUMP((IS_FLAG_CLEAR(C_FLAG))); \}#define BCS() \{ \   RELATIVE_JUMP((IS_FLAG_SET(C_FLAG))); \}#define BEQ() \{ \   RELATIVE_JUMP((IS_FLAG_SET(Z_FLAG))); \}#define BIT(cycles, read_func) \{ \   read_func(data); \   TEST_AND_FLAG(0 == (data & A), Z_FLAG);\   CLEAR_FLAG(N_FLAG | V_FLAG); \   /* move bit 7/6 of data into N/V flags */ \   SET_FLAG(data & (N_FLAG | V_FLAG)); \   ADD_CYCLES(cycles); \}#define BMI() \{ \   RELATIVE_JUMP((IS_FLAG_SET(N_FLAG))); \}#define BNE() \{ \   RELATIVE_JUMP((IS_FLAG_CLEAR(Z_FLAG))); \}#define BPL() \{ \   RELATIVE_JUMP((IS_FLAG_CLEAR(N_FLAG))); \}/* Software interrupt type thang */#define BRK() \{ \   PC++; \   PUSH(PC >> 8); \   PUSH(PC & 0xFF); \   SET_FLAG(B_FLAG); \   PUSH(P); \   SET_FLAG(I_FLAG); \   JUMP(IRQ_VECTOR); \   ADD_CYCLES(7); \}#define BVC() \{ \   RELATIVE_JUMP((IS_FLAG_CLEAR(V_FLAG))); \}#define BVS() \{ \   RELATIVE_JUMP((IS_FLAG_SET(V_FLAG))); \}#define CLC() \{ \   CLEAR_FLAG(C_FLAG); \   ADD_CYCLES(2); \}#define CLD() \{ \   CLEAR_FLAG(D_FLAG); \   ADD_CYCLES(2); \}#define CLI() \{ \   CLEAR_FLAG(I_FLAG); \   ADD_CYCLES(2); \}#define CLV() \{ \   CLEAR_FLAG(V_FLAG); \   ADD_CYCLES(2); \}/* TODO: ick! */#define _COMPARE(reg, value) \{ \   temp = (reg) - (value); \   /* C is clear when data > A */ \   TEST_AND_FLAG(0 == (temp & 0x8000), C_FLAG); \   SET_NZ_FLAGS((uint8) temp); /* handles Z flag */ \}#define CMP(cycles, read_func) \{ \   read_func(data); \   _COMPARE(A, data); \   ADD_CYCLES(cycles); \}#define CPX(cycles, read_func) \{ \   read_func(data); \   _COMPARE(X, data); \   ADD_CYCLES(cycles); \}#define CPY(cycles, read_func) \{ \   read_func(data); \   _COMPARE(Y, data); \   ADD_CYCLES(cycles); \}/* undocumented */#define DCP(cycles, read_func, write_func, addr) \{ \   read_func(addr, data); \   data--; \   write_func(addr, data); \   CMP(cycles, NO_READ); \}#define DEC(cycles, read_func, write_func, addr) \{ \   read_func(addr, data); \   data--; \   write_func(addr, data); \   SET_NZ_FLAGS(data); \   ADD_CYCLES(cycles); \}#define DEX() \{ \   X--; \   SET_NZ_FLAGS(X); \   ADD_CYCLES(2); \}#define DEY() \{ \   Y--; \   SET_NZ_FLAGS(Y); \   ADD_CYCLES(2); \}/* undocumented (double-NOP) */#define DOP(cycles) \{ \   PC++; \   ADD_CYCLES(cycles); \}#define EOR(cycles, read_func) \{ \   read_func(data); \   A ^= data; \   SET_NZ_FLAGS(A); \   ADD_CYCLES(cycles); \}#define INC(cycles, read_func, write_func, addr) \{ \   read_func(addr, data); \   data++; \   write_func(addr, data); \   SET_NZ_FLAGS(data); \   ADD_CYCLES(cycles); \}#define INX() \{ \   X++; \   SET_NZ_FLAGS(X); \   ADD_CYCLES(2); \}#define INY() \{ \   Y++; \   SET_NZ_FLAGS(Y); \   ADD_CYCLES(2); \}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -