IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 第五篇:手把手教你移植任天堂没有声音、无需外置SD卡、可使用独立按键也可使用外置手柄,本人使用的芯片为ESP32,移植到STM32均可使用。(本篇完结nes模拟器的移植) -> 正文阅读

[嵌入式]第五篇:手把手教你移植任天堂没有声音、无需外置SD卡、可使用独立按键也可使用外置手柄,本人使用的芯片为ESP32,移植到STM32均可使用。(本篇完结nes模拟器的移植)

话不多说,上代码

打开nes.main.c文件

添加如下代码

u8 nesruning = 0;       //初始化为真
u8 frame_cnt;           //统计帧数
//u8  *rom_file;          //NES游戏rom的存储地址
//NES 帧周期循环
void NesFrameCycle(void)
{
    int clocks; //CPU执行时间
    static int NES_time;
    //启动模拟器循环,检查VROM设置,若卡带为0,初始化VROM
    //if ( NesHeader.byVRomSize == 0)
    //设置VROM存储区位置。
    frame_cnt = 0;
    nesruning = 1;
    while (nesruning)
    {

        //scanline: 0~19 VBANK 段,若PPU使能NMI,将产生NMI 中断
        frame_cnt++;//帧计数器
        SpriteHitFlag = 0;
        for (PPU_scanline = 0; PPU_scanline < 20; PPU_scanline++)
        {
            exec6502(CLOCKS_PER_SCANLINE);
        }
        //scanline: 20, PPU加载设置,执行一次空的扫描时间
        exec6502(CLOCKS_PER_SCANLINE);
        //NesHBCycle();  //水平周期
        PPU_scanline++;   //20++
        PPU_Reg.NES_R2 &= ~R2_SPR0_HIT;
        //scanline: 21~261

        for (; PPU_scanline < SCAN_LINE_DISPALY_END_NUM; PPU_scanline++)
        {

            if ((SpriteHitFlag == 1) && ((PPU_Reg.NES_R2 & R2_SPR0_HIT) == 0))
            {
                clocks = sprite[0].x * CLOCKS_PER_SCANLINE / NES_DISP_WIDTH;
                exec6502(clocks);  //需重点优化
                PPU_Reg.NES_R2 |= R2_SPR0_HIT;
                exec6502(CLOCKS_PER_SCANLINE - clocks);
            }
            else exec6502(CLOCKS_PER_SCANLINE);   //耗时大户


            if (PPU_Reg.NES_R1 & (R1_BG_VISIBLE | R1_SPR_VISIBLE)) //若为假,关闭显示
            {
                if (SpriteHitFlag == 0)
                    NES_GetSpr0HitFlag(PPU_scanline - SCAN_LINE_DISPALY_START_NUM);//查找Sprite #0 碰撞标志
            }
            if ((frame_cnt % 3) == 0) //每3帧显示一次      //耗时大户
            {
                NES_time = micros()  ;
                NES_RenderLine(PPU_scanline - SCAN_LINE_DISPALY_START_NUM);//水平同步与显示一行
                printf("%d\n", micros() - NES_time);
            }
        }

        //scanline: 262 完成一帧
        exec6502(CLOCKS_PER_SCANLINE);
        PPU_Reg.NES_R2 |= R2_VBlank_Flag;//设置VBANK 标志
        //若使能PPU VBANK中断,则设置VBANK
        if (PPU_Reg.NES_R0 & R0_VB_NMI_EN)
        {
            NMI_Flag = SET1;//完成一帧扫描,产生NMI中断
        }
        //设置帧IRQ标志,同步计数器,APU等
        //A mapper function in V-Sync 存储器切换垂直VBANK同步
        //MapperVSync();
        //读取控制器JoyPad状态,更新JoyPad控制器值*/
        //NES_JoyPadUpdateValue();   //systick 中断读取按键值


        //单独的返回键(KEY6)扫描程序
        //  if(KEY_Scan_f())break;        //退出 //退出模拟器
    }
}

同时找到如下代码

printf("\r\n  开始申请内存\n");
    res = nes_mem_creat(); //申请内存
    if (res == 0) //申请成功了.则运行游戏
    {
        printf("\r\n  开始申请成功\n");
        printf("\r\n  初始化6502\n");



        LCD_tft_init();  //初始化显示设备
        PPU_Init(((u8 *)&rom_file[offset + 0x10] + 
                 (neshreader->romnum * 0x4000)),
                 (neshreader->romfeature & 0x01)
                ); //PPU_初始化



        key_init();       //初始化获取按键值设备
        adc_init();       //初始化获取方向值设备
        NES_JoyPadInit(); //初始化模拟手柄



        printf("\r\n  无限循环执行游戏\n");
        printf("\r\n  按下退出游戏键\n");
    }
    else   printf("\r\n  开始申请失败\n");
    nes_mem_delete();//释放内存
    return res;
}

改为

printf("\r\n  开始申请内存\n");
    res = nes_mem_creat(); //申请内存
    if (res == 0) //申请成功了.则运行游戏
    {
        printf("\r\n  开始申请成功\n");
        init6502mem(0,   //exp_rom                                                                                         
                    0,   //sram 由卡类型决定, 暂不支持                                                                                            
                  ((u8 *)&rom_file[offset + 0x10]),  //prg_rombank, 存储器大小 由卡类型决定                                                              
                    neshreader->romnum);                                                                             
        reset6502();  //初始化6502存储器镜像



        LCD_tft_init();  //初始化显示设备
        PPU_Init(((u8 *)&rom_file[offset + 0x10] + 
                 (neshreader->romnum * 0x4000)),
                 (neshreader->romfeature & 0x01)
                ); //PPU_初始化



        key_init();       //初始化获取按键值设备
        adc_init();       //初始化获取方向值设备
        NES_JoyPadInit(); //初始化模拟手柄



        NesFrameCycle();//模拟器循环执行    



        printf("\r\n  按下退出游戏键\n");
    }
    else   printf("\r\n  开始申请失败\n");
    nes_mem_delete();//释放内存
    return res;
}

同时找到


//CPU使用
 u8 *ram6502;  			//RAM  2K字节,由malloc申请
portMUX_TYPE isr_nes_creat = portMUX_INITIALIZER_UNLOCKED;
 
//开辟nes运行所需的RAM.
//返回值:0,成功;
//    其他,错误代码.
u8 nes_mem_creat(void)
{
    portENTER_CRITICAL_ISR(&isr_nes_creat);
    ram6502 = (u8 *)malloc(2048); //申请2K内存
    if (ram6502 == NULL)return 1;       //申请失败
    NameTable = (u8 *)malloc(2048); //申请2K内存
    if (NameTable == NULL)return 2;
    Buffer_scanline = (u16 *)malloc((8 + 256 + 8) * 2);
    if (Buffer_scanline == NULL)return 3;
    portEXIT_CRITICAL_ISR(&isr_nes_creat);
    return 0;
}

删掉

//CPU使用
 u8 *ram6502;  			//RAM  2K字节,由malloc申请

然后在头文件添加

#include "6502.h"

编译通过即可

至此,NES模拟器就此完结,完整资源链接为:

下面贴出6502.c和6502.h文件

#include "6502.h"
	   


//6502标志位 flags = NVRBDIZC
#define	C_FLAG		0x01		// 1: Carry
#define	Z_FLAG		0x02		// 1: Zero
#define	I_FLAG		0x04		// 1: Irq disabled
#define	D_FLAG		0x08		// 1: Decimal mode flag (NES unused)
#define	B_FLAG		0x10		// 1: Break
#define	R_FLAG		0x20		// 1: Reserved (Always 1)
#define	V_FLAG		0x40		// 1: Overflow
#define	N_FLAG		0x80		// 1: Negative

// flags = NVRBDIZC  
BYTE a_reg,x_reg,y_reg,flag_reg,s_reg;
WORD pc_reg = 0;

//中断标志 
CPU_InitFlag NMI_Flag;
CPU_InitFlag IRQ_Flag;

// Macros for convenience  
#define A a_reg
#define X x_reg
#define Y y_reg
#define P flag_reg
#define S s_reg
#define PC pc_reg

//internal registers  	  
BYTE opcode;
int  clockticks6502;

//help variables 
WORD savepc;
BYTE value;
int  sum,saveflags;
WORD help;

//6502 memory map  
u8 *ram6502;  			//RAM  2K字节,由malloc申请
//u8* ppu_regbase;		// PPU IO reg 
//u8* apu_regbase;		// APU IO reg 
u8* exp_rom;	    	// expansion rom 
u8* sram;				// sram 
u8* prg_rombank0;		// prg-rom lower bank 
u8* prg_rombank1;		// prg-rom upper bank 

// arrays  
typedef struct
{
 	unsigned short int	ticks;
	void (*instruction)(void);//指令
	void (*adrmode)(void);	  //
}OPCODE;


const OPCODE opcodetable[]=
{
/*0x00*/ 	{7,	brk6502,	implied6502},
/*0x01*/	{6,	ora6502,	indx6502},
/*0x02*/	{2,	nop6502,	implied6502},
/*0x03*/	{2,	nop6502,	implied6502},
/*0x04*/	{3,	tsb6502,	zp6502},
/*0x05*/	{3,	ora6502,	zp6502},
/*0x06*/	{5,	asl6502,	zp6502},
/*0x07*/	{2,	nop6502,	implied6502},
/*0x08*/	{3,	php6502,	implied6502},
/*0x09*/	{3,	ora6502,	immediate6502},
/*0x0A*/	{2,	asla6502,	implied6502},
/*0x0B*/	{2,	ora6502,	implied6502},
/*0x0C*/	{4,	tsb6502,	abs6502},
/*0x0D*/	{4,	ora6502,	abs6502},
/*0x0E*/	{6,	asl6502,	abs6502},
/*0x0F*/	{2,	nop6502,	implied6502},

/*0x10*/ 	{2,	bpl6502,	relative6502},
/*0x11*/	{5,	ora6502,	indy6502},
/*0x12*/	{3,	ora6502,	indzp6502},
/*0x13*/	{2,	nop6502,	implied6502},
/*0x14*/	{3,	trb6502,	zp6502},
/*0x15*/	{4,	ora6502,	zpx6502},
/*0x16*/	{6,	asl6502,	zpx6502},
/*0x17*/	{2,	nop6502,	implied6502},
/*0x18*/	{2,	clc6502,	implied6502},
/*0x19*/	{4,	ora6502,	absy6502},
/*0x1A*/	{2,	ina6502,	implied6502},
/*0x1B*/	{2,	nop6502,	implied6502},
/*0x1C*/	{4,	trb6502,	abs6502},
/*0x1D*/	{4,	ora6502,	absx6502},
/*0x1E*/	{7,	asl6502,	absx6502},
/*0x1F*/	{2,	nop6502,	implied6502},

/*0x20*/ 	{6,	jsr6502,	abs6502},
/*0x21*/	{6,	and6502,	indx6502},
/*0x22*/	{2,	nop6502,	implied6502},
/*0x23*/	{2,	nop6502,	implied6502},
/*0x24*/	{3,	bit6502,	zp6502},
/*0x25*/	{3,	and6502,	zp6502},
/*0x26*/	{5,	rol6502,	zp6502},
/*0x27*/	{2,	nop6502,	implied6502},
/*0x28*/	{4,	plp6502,	implied6502},
/*0x29*/	{3,	and6502,	immediate6502},
/*0x2A*/	{2,	rola6502,	implied6502},
/*0x2B*/	{2,	nop6502,	implied6502},
/*0x2C*/	{4,	bit6502,	abs6502},
/*0x2D*/	{4,	and6502,	abs6502},
/*0x2E*/	{6,	rol6502,	abs6502},
/*0x2F*/	{2,	nop6502,	implied6502},

/*0x30*/ 	{2,	bmi6502,	relative6502},
/*0x31*/	{5,	and6502,	indy6502},
/*0x32*/	{3,	and6502,	indzp6502},
/*0x33*/	{2,	nop6502,	implied6502},
/*0x34*/	{4,	bit6502,		zpx6502},
/*0x35*/	{4,	and6502,	zpx6502},
/*0x36*/	{6,	rol6502,	zpx6502},
/*0x37*/	{2,	nop6502,	implied6502},
/*0x38*/	{2,	sec6502,	implied6502},
/*0x39*/	{4,	and6502,	absy6502},
/*0x3A*/	{2,	dea6502,	implied6502},
/*0x3B*/	{2,	nop6502,	implied6502},
/*0x3C*/	{4,	bit6502,	absx6502},
/*0x3D*/	{4,	and6502,	absx6502},
/*0x3E*/	{7,	rol6502,	absx6502},
/*0x3F*/	{2,	nop6502,	implied6502},

/*0x40*/ 	{6,	rti6502,	implied6502},
/*0x41*/	{6,	eor6502,	indx6502},
/*0x42*/	{2,	nop6502,	implied6502},
/*0x43*/	{2,	nop6502,	implied6502},
/*0x44*/	{2,	nop6502,	implied6502},
/*0x45*/	{3,	eor6502,	zp6502},
/*0x46*/	{5,	lsr6502,	zp6502},
/*0x47*/	{2,	nop6502,	implied6502},
/*0x48*/	{3,	pha6502,	implied6502},
/*0x49*/	{3,	eor6502,	immediate6502},
/*0x4A*/	{2,	lsra6502,	implied6502},
/*0x4B*/	{2,	nop6502,	implied6502},
/*0x4C*/	{3,	jmp6502,	abs6502},
/*0x4D*/	{4,	eor6502,	abs6502},
/*0x4E*/	{6,	lsr6502,	abs6502},
/*0x4F*/	{2,	nop6502,	implied6502},

/*0x50*/ 	{2,	bvc6502,	relative6502},
/*0x51*/	{5,	eor6502,	indy6502},
/*0x52*/	{3,	eor6502,	indzp6502},
/*0x53*/	{2,	nop6502,	implied6502},
/*0x54*/	{2,	nop6502,	implied6502},
/*0x55*/	{4,	eor6502,	zpx6502},
/*0x56*/	{6,	lsr6502,	zpx6502},
/*0x57*/	{2,	nop6502,	implied6502},
/*0x58*/	{2,	cli6502,	implied6502},
/*0x59*/	{4,	eor6502,	absy6502},
/*0x5A*/	{3,	phy6502,	implied6502},
/*0x5B*/	{2,	nop6502,	implied6502},
/*0x5C*/	{2,	nop6502,	implied6502},
/*0x5D*/	{4,	eor6502,	absx6502},
/*0x5E*/	{7,	lsr6502,	absx6502},
/*0x5F*/	{2,	nop6502,	implied6502},

/*0x60*/ 	{6,	rts6502,	implied6502},
/*0x61*/	{6,	adc6502,	indx6502},
/*0x62*/	{2,	nop6502,	implied6502},
/*0x63*/	{2,	nop6502,	implied6502},
/*0x64*/	{3,	stz6502,	zp6502},
/*0x65*/	{3,	adc6502,	zp6502},
/*0x66*/	{5,	ror6502,	zp6502},
/*0x67*/	{2,	nop6502,	implied6502},
/*0x68*/	{4,	pla6502,	implied6502},
/*0x69*/	{3,	adc6502,	immediate6502},
/*0x6A*/	{2,	rora6502,	implied6502},
/*0x6B*/	{2,	nop6502,	implied6502},
/*0x6C*/	{5,	jmp6502,	indirect6502},
/*0x6D*/	{4,	adc6502,	abs6502},
/*0x6E*/	{6,	ror6502,	abs6502},
/*0x6F*/	{2,	nop6502,	implied6502},

/*0x70*/ 	{2,	bvs6502,	implied6502},
/*0x71*/	{5,	adc6502,	indy6502},
/*0x72*/	{3,	adc6502,	indzp6502},
/*0x73*/	{2,	nop6502,	implied6502},
/*0x74*/	{4,	stz6502,	zpx6502},
/*0x75*/	{4,	adc6502,	zpx6502},
/*0x76*/	{6,	ror6502,	zpx6502},
/*0x77*/	{2,	nop6502,	implied6502},
/*0x78*/	{2,	sei6502,	implied6502},
/*0x79*/	{4,	adc6502,	absy6502},
/*0x7A*/	{4,	ply6502,	implied6502},
/*0x7B*/	{2,	nop6502,	implied6502},
/*0x7C*/	{6,	jmp6502,	indabsx6502},
/*0x7D*/	{4,	adc6502,	absx6502},
/*0x7E*/	{7,	ror6502,	absx6502},
/*0x7F*/	{2,	nop6502,	implied6502},

/*0x80*/ 	{2,	bra6502,	relative6502},
/*0x81*/	{6,	sta6502,	indx6502},
/*0x82*/	{2,	nop6502,	implied6502},
/*0x83*/	{2,	nop6502,	implied6502},
/*0x84*/	{2,	sty6502,	zp6502},
/*0x85*/	{2,	sta6502,	zp6502},
/*0x86*/	{2,	stx6502,	zp6502},
/*0x87*/	{2,	nop6502,	implied6502},
/*0x88*/	{2,	dey6502,	implied6502},
/*0x89*/	{2,	bit6502,	immediate6502},
/*0x8A*/	{2,	txa6502,	implied6502},
/*0x8B*/	{2,	nop6502,	implied6502},
/*0x8C*/	{4,	sty6502,	abs6502},
/*0x8D*/	{4,	sta6502,	abs6502},
/*0x8E*/	{4,	stx6502,	abs6502},
/*0x8F*/	{2,	nop6502,	implied6502},

/*0x90*/ 	{2,	bcc6502,	relative6502},
/*0x91*/	{6,	sta6502,	indy6502},
/*0x92*/	{3,	sta6502,	indzp6502},
/*0x93*/	{2,	nop6502,	implied6502},
/*0x94*/	{4,	sty6502,	zpx6502},
/*0x95*/	{4,	sta6502,	zpx6502},
/*0x96*/	{4,	stx6502,	zpy6502},
/*0x97*/	{2,	nop6502,	implied6502},
/*0x98*/	{2,	tya6502,	implied6502},
/*0x99*/	{5,	sta6502,	absy6502},
/*0x9A*/	{2,	txs6502,	implied6502},
/*0x9B*/	{2,	nop6502,	implied6502},
/*0x9C*/	{4,	stz6502,	abs6502},
/*0x9D*/	{5,	sta6502,	absx6502},
/*0x9E*/	{5,	stz6502,	absx6502},
/*0x9F*/	{2,	nop6502,	implied6502},

/*0xA0*/ 	{3,	ldy6502,	immediate6502},
/*0xA1*/	{6,	lda6502,	indx6502},
/*0xA2*/	{3,	ldx6502,	immediate6502},
/*0xA3*/	{2,	nop6502,	implied6502},
/*0xA4*/	{3,	ldy6502,	zp6502},
/*0xA5*/	{3,	lda6502,	zp6502},
/*0xA6*/	{3,	ldx6502,	zp6502},
/*0xA7*/	{2,	nop6502,	implied6502},
/*0xA8*/	{2,	tay6502,	implied6502},
/*0xA9*/	{3,	lda6502,	immediate6502},
/*0xAA*/	{2,	tax6502,	implied6502},
/*0xAB*/	{2,	nop6502,	implied6502},
/*0xAC*/	{4,	ldy6502,	abs6502},
/*0xAD*/	{4,	lda6502,	abs6502},
/*0xAE*/	{4,	ldx6502,	abs6502},
/*0xAF*/	{2,	nop6502,	implied6502},

/*0xB0*/ 	{2,	bcs6502,	relative6502},
/*0xB1*/	{5,	lda6502,	indy6502},
/*0xB2*/	{3,	lda6502,	indzp6502},
/*0xB3*/	{2,	nop6502,	implied6502},
/*0xB4*/	{4,	ldy6502,	zpx6502},
/*0xB5*/	{4,	lda6502,	zpx6502},
/*0xB6*/	{4,	ldx6502,	zpy6502},
/*0xB7*/	{2,	nop6502,	implied6502},
/*0xB8*/	{2,	clv6502,	implied6502},
/*0xB9*/	{4,	lda6502,	absy6502},
/*0xBA*/	{2,	tsx6502,	implied6502},
/*0xBB*/	{2,	nop6502,	implied6502},
/*0xBC*/	{4,	ldy6502,	absx6502},
/*0xBD*/	{4,	lda6502,	absx6502},
/*0xBE*/	{4,	ldx6502,	absy6502},
/*0xBF*/	{2,	nop6502,	implied6502},

/*0xC0*/ 	{3,	cpy6502,	immediate6502},
/*0xC1*/	{6,	cmp6502,	indx6502},
/*0xC2*/	{2,	nop6502,	implied6502},
/*0xC3*/	{2,	nop6502,	implied6502},
/*0xC4*/	{3,	cpy6502,	zp6502},
/*0xC5*/	{3,	cmp6502,	zp6502},
/*0xC6*/	{5,	dec6502,	zp6502},
/*0xC7*/	{2,	nop6502,	implied6502},
/*0xC8*/	{2,	iny6502,	implied6502},
/*0xC9*/	{3,	cmp6502,	immediate6502},
/*0xCA*/	{2,	dex6502,	implied6502},
/*0xCB*/	{2,	nop6502,	implied6502},
/*0xCC*/	{4,	cpy6502,	abs6502},
/*0xCD*/	{4,	cmp6502,	abs6502},
/*0xCE*/	{6,	dec6502,	abs6502},
/*0xCF*/	{2,	nop6502,	implied6502},

/*0xD0*/ 	{2,	bne6502,	relative6502},
/*0xD1*/	{5,	cmp6502,	indy6502},
/*0xD2*/	{3,	cmp6502,	indzp6502},
/*0xD3*/	{2,	nop6502,	implied6502},
/*0xD4*/	{2,	nop6502,	implied6502},
/*0xD5*/	{4,	cmp6502,	zpx6502},
/*0xD6*/	{6,	dec6502,	zpx6502},
/*0xD7*/	{2,	nop6502,	implied6502},
/*0xD8*/	{2,	cld6502,	implied6502},
/*0xD9*/	{4,	cmp6502,	absy6502},
/*0xDA*/	{3,	phx6502,	implied6502},
/*0xDB*/	{2,	nop6502,	implied6502},
/*0xDC*/	{2,	nop6502,	implied6502},
/*0xDD*/	{4,	cmp6502,	absx6502},
/*0xDE*/	{7,	dec6502,	absx6502},
/*0xDF*/	{2,	nop6502,	implied6502},

/*0xE0*/ 	{3,	cpx6502,	immediate6502},
/*0xE1*/	{6,	sbc6502,	indx6502},
/*0xE2*/	{2,	nop6502,	implied6502},
/*0xE3*/	{2,	nop6502,	implied6502},
/*0xE4*/	{3,	cpx6502,	zp6502},
/*0xE5*/	{3,	sbc6502,	zp6502},
/*0xE6*/	{5,	inc6502,	zp6502},
/*0xE7*/	{2,	nop6502,	implied6502},
/*0xE8*/	{2,	inx6502,	implied6502},
/*0xE9*/	{3,	sbc6502,	immediate6502},
/*0xEA*/	{2,	nop6502,	implied6502},
/*0xEB*/	{2,	nop6502,	implied6502},
/*0xEC*/	{4,	cpx6502,	abs6502},
/*0xED*/	{4,	sbc6502,	abs6502},
/*0xEE*/	{6,	inc6502,	abs6502},
/*0xEF*/	{2,	nop6502,	implied6502},

/*0xF0*/ 	{2,	beq6502,	relative6502},
/*0xF1*/	{5,	sbc6502,	indy6502},
/*0xF2*/	{3,	sbc6502,	indzp6502},
/*0xF3*/	{2,	nop6502,	implied6502},
/*0xF4*/	{2,	nop6502,	implied6502},
/*0xF5*/	{4,	sbc6502,	zpx6502},
/*0xF6*/	{6,	inc6502,	zpx6502},
/*0xF7*/	{2,	nop6502,	implied6502},
/*0xF8*/	{2,	sed6502,	implied6502},
/*0xF9*/	{4,	sbc6502,	absy6502},
/*0xFA*/	{4,	plx6502,	implied6502},
/*0xFB*/	{2,	nop6502,	implied6502},
/*0xFC*/	{2,	nop6502,	implied6502},
/*0xFD*/	{4,	sbc6502,	absx6502},
/*0xFE*/	{7,	inc6502,	absx6502},
/*0xFF*/	{2,	nop6502,	implied6502}
};

//
//6502 存储器镜像读写 	   
//

//sprite DMA (写地址到$4014, 左移8位,原数据地址)
void SprDMA(BYTE scr_addr) 		//scr_addr 为高8位地址
{
	u8 *scr_addrptr = 0;		//将传送sprite数据 指针
	int 	i;	  
	switch(scr_addr >> 4)//选择源地址数据区域
	{		
		case 0x0: //RAM
		case 0x1: scr_addrptr = &ram6502[(scr_addr << 8)];
			break;
		case 0x6: //SRAM
		case 0x7: 
		#ifdef CHECK_POINTER
			check_pointer(sram); 
		#endif
			scr_addrptr = sram + ((scr_addr << 8) - 0x6000);
			break;
		case 0x8:	//程序存储器 只读 
		case 0x9:
		case 0xA:
		case 0xB:
		#ifdef CHECK_POINTER
			check_pointer(prg_rombank0); 
		#endif
			scr_addrptr = &prg_rombank0[(scr_addr << 8) - 0x8000];
			break;
		case 0xC:
		case 0xD:
		case 0xE:
		case 0xF:
			#ifdef CHECK_POINTER
				check_pointer(prg_rombank1); 
			#endif
			scr_addrptr = &prg_rombank1[(scr_addr << 8) - 0xC000];
			break;
	}   
#ifdef CKECK_POINTER
	if(scr_addrptr == NULL)
	{
		printf("\r\nSprite ram DMA 地址参数错误!");
		return;
	}
#endif	   
	for(i=0; i<256; i++)
	{
		Spr_Mem.spr_ram[i] = scr_addrptr[i];
	}											    
	//每次传输,需要512 cycles (about 4.5 scanlines worth)	   
	clockticks6502 -= 512;//花掉512CPU时钟周期  
}

//读取6502存储器		  
int get6502memory(WORD addr)//没0x2000递增
{
   	switch(addr & 0xE000)
	{
		case 0x0000:	//$0000 ~ $0FFF	
			return (ram6502[addr&0x7FF]);
		case 0x1000:	//$1000 ~ $1FFF	镜像
			return (ram6502[addr&0x7FF]);
 		case 0x2000:	//$2000 ~ $2FFF
			return PPU_RegRead(addr&0x7);	//PPU IO接口 	
		//case 0x3000:	//$3000 ~ $3FFF		镜像
			//break;
		case 0x4000://$4000 ~ $4FFF	 //暂不处理
			//APU 声音处理 IO接口 扩展ROM 
			//if(addr < 0x4013)return (apu_regbase[addr&0x1F]); //暂不处理	  
			//if(addr == 0x4014){SpriteRAM_DMA();break;} 		//只支持写	   
			//if(addr == 0x4015);//pAPU Sound / Vertical Clock Signal Register	   
			if(addr == 0x4016)
			{
				return NES_GetJoyPadVlaue(JOYPAD_0)|0x40;//分为3段8bit数据,第一段8bit为控制器1,第二段控制器3,第三段ID code
			}
			if(addr == 0x4017)
			{
				return NES_GetJoyPadVlaue2(JOYPAD_0);//分为3段8bit数据,第一段8bit为控制器2,第二段控制器4,第三段ID code
			}
			break;
		//case 0x5000:// expansion rom*/
		//#ifdef CKECK_POINTER
		//		 check_pointer(exp_rom); 
		//#endif
		//		 return (exp_rom[addr - 0x4020]);
		case 0x6000://卡带SRAM,一般用来存储游戏进度 
		#ifdef CKECK_POINTER
			check_pointer(ram6502); 
		#endif
			//暂不处理 	 
			break;
		case 0x8000://程序存储器 只读 
		case 0xA000:
		#ifdef CHECK_POINTER
			check_pointer(prg_rombank0); 
		#endif
			return prg_rombank0[addr-0x8000];
		case 0xC000:
		case 0xE000:
		#ifdef CHECK_POINTER
			check_pointer(prg_rombank1); 
		#endif
			return prg_rombank1[addr-0xC000];				   
	}	   
    return (addr >> 8);//通常不会执行到此处,返回地址高八位
					   //APU和SRAM未完成,可能执行到此处*/ 
}

//写6502存储器	   
void put6502memory(WORD addr, BYTE value)
{
	switch(addr & 0xE000)
	{
		case 0x0000:
			ram6502[addr&0x7FF] = value;
			break;
		case 0x2000://PPU IO接口 
			PPU_RegWrite(addr&0x7, value);
			break;
		case 0x4000:	//APU 声音处理 IO接口 扩展ROM 
			if(addr == 0x4014)SprDMA(value); //value 为将要传送的数据地址的高八位  
			if(addr == 0x4016)
			{   
				//bit0 JoyPad 控制 
				if(value & 1)//先写bit0:1复位按键状态,在写bit0:0禁止
				{	   
					NES_JoyPadReset();
				}else NES_JoyPadDisable();   
			}
			//其他位暂未使用 
			//if(addr == 0x4017)NES_SetJoyPad(value); 
			//if(addr >= 0x4020){
			//		 	exp_rom[addr - 0x6000] = value;
			//		 }
			//其余寄存器暂未处理
			break;
		case 0x6000://卡带SRAM,一般用来存储游戏进度*/
		//#ifdef CHECK_POINTER
		//		 check_pointer(sram); 
		//#endif
		//		 sram[addr - 0x6000] = value; //与存储器切换有关	 
			break;
		case 0x8000:	//程序存储器 只读(写入时与存储器切换(mapper)有关,暂略) 
		case 0xA000:
		case 0xC000:
		case 0xE000:
			//Write to Mapper
			//MapperWrite( wAddr, byData );
			break;
	}
}
//
//寻址模式	   
//

//Adressing modes  
//Implied  
void implied6502(void)
{
}

//#Immediate  
void immediate6502(void)
{
	savepc=PC++;
}   
//ABS 
void abs6502(void)
{															
	//savepc = gameImage[PC] + (gameImage[PC + 1] << 8);
	savepc=get6502memory(PC)+(get6502memory(PC+1) << 8);	 
	PC+=2;  
}   
//Branch  
void relative6502(void)
{
	//savepc = gameImage[PC++];
	savepc  = get6502memory(PC++);	  
	if(savepc & 0x80)savepc-=0x100;
    if((savepc>>8)!=(PC>>8))clockticks6502++;	    
}  
//(ABS)  
void indirect6502(void)
{
	//help = gameImage[PC] + (gameImage[PC + 1] << 8);
	//savepc = gameImage[help] + (gameImage[help + 1] << 8);
	help    =  get6502memory(PC)+(get6502memory(PC+1) << 8);
 	savepc  =  get6502memory(help)+(get6502memory(help+1) << 8); 
 	PC+=2;
}   
//ABS,X
void absx6502(void)
{
	//savepc = gameImage[PC] + (gameImage[PC + 1] << 8);
	savepc=get6502memory(PC)+(get6502memory(PC+1) << 8);	  
    PC+=2;
    if(opcodetable[opcode].ticks==4)
		if ((savepc>>8) != ((savepc+X)>>8))clockticks6502++;	 
    savepc += X;
}  
// ABS,Y  
void absy6502(void)
{
	//savepc = gameImage[PC] + (gameImage[PC + 1] << 8);
	savepc  = get6502memory(PC)+(get6502memory(PC+1) << 8);
  	PC+=2;	 
	if (opcodetable[opcode].ticks==4)
		if ((savepc>>8) != ((savepc+Y)>>8))clockticks6502++;    
	savepc += Y;
}  
//ZP 
void zp6502(void)
{
	//savepc=gameImage[PC++];
	savepc  = get6502memory(PC);
	PC++;
}

/* ZP,X */
void zpx6502(void)
{
//	savepc=gameImage[PC++]+X;
	savepc  = get6502memory(PC) + X;
	PC++;

	savepc &= 0x00ff;
}

//ZP,Y 
void zpy6502(void)
{
	//savepc=gameImage[PC++]+Y;
	savepc  = get6502memory(PC) + Y;
	PC++; 
    savepc &= 0x00ff;
}	 
//(ZP,X)  
void indx6502(void)
{
	//value = gameImage[PC++]+X;
	//savepc = gameImage[value] + (gameImage[value+1] << 8);
	value = get6502memory(PC) + Y;
	PC++;	
	savepc  = get6502memory(value)+(get6502memory(value + 1) << 8);  
}

//(ZP),Y 
void indy6502(void)
{
	//value = gameImage[PC++];
	//savepc = gameImage[value] + (gameImage[value+1] << 8);
	value = get6502memory(PC);
	PC++;
	savepc  = get6502memory(value)+(get6502memory(value + 1) << 8);  
 	if (opcodetable[opcode].ticks==5)
	      if ((savepc>>8) != ((savepc+Y)>>8))clockticks6502++;	  
	savepc += Y;
}

/* (ABS,X) */
void indabsx6502(void)
{
	//help = gameImage[PC] + (gameImage[PC + 1] << 8) + X;
	//savepc = gameImage[help] + (gameImage[help + 1] << 8);
	help 	= get6502memory(PC)+((get6502memory(PC+1) << 8) +X);  
	savepc  = get6502memory(help)+(get6502memory(help + 1) << 8);  
}

//(ZP) 
void indzp6502(void)
{
	//value = gameImage[PC++];
	//savepc = gameImage[value] + (gameImage[value + 1] << 8);
	value = get6502memory(PC);
	PC++;
	savepc  = get6502memory(value)+( get6502memory(value + 1) << 8 );  
}

//
//指令	   
//

 
//Instructions  
void adc6502(void)
{
	opcodetable[opcode].adrmode();	 
	value = get6502memory(savepc);	  
	saveflags=(P & 0x01);
	sum= ((char) A) + ((char) value) + saveflags;
	if ((sum>0x7f) || (sum<-0x80)) P |= 0x40; 
	else P &= 0xbf;
	sum= A + value + saveflags;
	if (sum>0xff) P |= 0x01; 
	else P &= 0xfe;
	A=sum;
	if (P & 0x08)
	{
		P &= 0xfe;
		if ((A & 0x0f)>0x09)A += 0x06;  
		if ((A & 0xf0)>0x90)
		{
			A += 0x60;
			P |= 0x01;
		}
	}else clockticks6502++;	   
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void and6502(void)
{
	opcodetable[opcode].adrmode();	  
	value = get6502memory(savepc);		 
	A &= value;
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void asl6502(void)
{
	opcodetable[opcode].adrmode();
	value = get6502memory(savepc);
	P= (P & 0xfe) | ((value >>7) & 0x01);
	value = value << 1;
	put6502memory(savepc,value);
	if (value) P &= 0xfd; 
	else P |= 0x02;
	if (value & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void asla6502(void)
{
	P= (P & 0xfe) | ((A >>7) & 0x01);
	A = A << 1;
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80;
	else P &= 0x7f;
}

void bcc6502(void)
{
	if ((P & 0x01)==0)
	{
		opcodetable[opcode].adrmode();
		PC += savepc;
		clockticks6502++;
	}else value = get6502memory(PC++);  
}

void bcs6502(void)
{
	if (P & 0x01)
	{
		opcodetable[opcode].adrmode();
		PC += savepc;
		clockticks6502++;
	}else value = get6502memory(PC++);	 
}

void beq6502(void)
{
	if (P & 0x02)
	{
		opcodetable[opcode].adrmode();
		PC += savepc;
		clockticks6502++;
	}else value = get6502memory(PC++); 
}

void bit6502(void)
{
	opcodetable[opcode].adrmode();
 	value = get6502memory(savepc); 
	//non-destrucive logically And between value and the accumulator
	//and set zero flag  
	if (value & A) P &= 0xfd; 
	else P |= 0x02;	   
	//set negative and overflow flags from value  
	P = (P & 0x3f) | (value & 0xc0);
}

void bmi6502(void)
{
    if (P & 0x80)
	{
		opcodetable[opcode].adrmode();
		PC += savepc;
		clockticks6502++;
	}else value = get6502memory(PC++);
}

void bne6502(void)
{
	if ((P & 0x02)==0)
	{
	    opcodetable[opcode].adrmode();
	    PC += savepc;
	    clockticks6502++;
	}else value = get6502memory(PC++);
}

void bpl6502(void)
{
	if ((P & 0x80)==0)	
	{
	    opcodetable[opcode].adrmode();
	    PC += savepc;
	    clockticks6502++;
	}else value = get6502memory(PC++);
}

void brk6502(void)
{
	PC++;
	put6502memory(0x0100+S--,(BYTE)(PC>>8));
	put6502memory(0x0100+S--,(BYTE)(PC & 0xff));
	put6502memory(0x0100+S--,P);
  	P |= 0x14;
 	PC = get6502memory(0xFFFE) + (get6502memory(0xFFFF) << 8);
}

void bvc6502(void)
{
    if ((P & 0x40)==0)
	{
		opcodetable[opcode].adrmode();
		PC += savepc;
		clockticks6502++;
	}else value = get6502memory(PC++);
}

void bvs6502(void)
{
	if (P & 0x40)
	{
	      opcodetable[opcode].adrmode();
	      PC += savepc;
	      clockticks6502++;
	}else value = get6502memory(PC++);
}

void clc6502(void)
{
	P &= 0xfe;
}

void cld6502(void)
{
	P &= 0xf7;
}

void cli6502(void)
{
	P &= 0xfb;
}

void clv6502(void)
{
	P &= 0xbf;
}

void cmp6502(void)
{
	opcodetable[opcode].adrmode();
	value = get6502memory(savepc);
	if (A+0x100-value>0xff) P |= 0x01; 
	else P &= 0xfe;
	value=A+0x100-value;
	if (value) P &= 0xfd; 
	else P |= 0x02;
	if (value & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void cpx6502(void)
{
	opcodetable[opcode].adrmode();
	value = get6502memory(savepc);
	if (X+0x100-value>0xff) P |= 0x01; 
	else P &= 0xfe;
	value=X+0x100-value;
	if (value) P &= 0xfd; 
	else P |= 0x02;
	if (value & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void cpy6502(void)
{
	opcodetable[opcode].adrmode();
	value = get6502memory(savepc);
	if (Y+0x100-value>0xff) P |= 0x01; 
	else P &= 0xfe;
	value=Y+0x100-value;
	if (value) P &= 0xfd; 
	else P |= 0x02;
	if (value & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void dec6502(void)
{
	u8 temp;	    
	opcodetable[opcode].adrmode();	   
	temp = get6502memory(savepc);
	temp--;
	put6502memory(savepc, temp);	    
	value = get6502memory(savepc);
	if (value) P &= 0xfd; 
	else P |= 0x02;
	if (value & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void dex6502(void)
{
	X--;
	if (X) P &= 0xfd; 
	else P |= 0x02;
	if (X & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void dey6502(void)
{
	Y--;
	if (Y) P &= 0xfd; 
	else P |= 0x02;
	if (Y & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void eor6502(void)
{
	opcodetable[opcode].adrmode();	   
	A ^= get6502memory(savepc);
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void inc6502(void)
{
	u8 temp;  	   
	opcodetable[opcode].adrmode();	 
	//gameImage[savepc]++;
	temp = get6502memory(savepc);
	temp++;
	put6502memory(savepc,temp);	    
	value = get6502memory(savepc);
	if (value) P &= 0xfd; 
	else P |= 0x02;
	if (value & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void inx6502(void)
{
	X++;
	if (X) P &= 0xfd; 
	else P |= 0x02;
	if (X & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void iny6502(void)
{
	Y++;
	if (Y) P &= 0xfd; 
	else P |= 0x02;
	if (Y & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void jmp6502(void)
{
	opcodetable[opcode].adrmode();
	PC=savepc;
}

void jsr6502(void)
{
	PC++;
	put6502memory(0x0100+S--,(BYTE)(PC >> 8));
	put6502memory(0x0100+S--,(BYTE)(PC & 0xff));
	PC--;
	opcodetable[opcode].adrmode();
	PC=savepc;
}

void lda6502(void)
{
	opcodetable[opcode].adrmode();
 	A = get6502memory(savepc);
	// set the zero flag
	if (A) P &= 0xfd; 
	else P |= 0x02;
	// set the negative flag
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void ldx6502(void)
{
	opcodetable[opcode].adrmode();
 	X = get6502memory(savepc);
	if (X) P &= 0xfd; 
	else P |= 0x02;
	if (X & 0x80) P |= 0x80;
	else P &= 0x7f;
}

void ldy6502(void)
{
	opcodetable[opcode].adrmode();
 	Y = get6502memory(savepc);
	if (Y) P &= 0xfd; 
	else P |= 0x02;
	if (Y & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void lsr6502(void)
{
	opcodetable[opcode].adrmode();
	value = get6502memory(savepc);	   
	//set carry flag if shifting right causes a bit to be lost  
	P= (P & 0xfe) | (value & 0x01);
 	value = value >>1;
	put6502memory(savepc,value);
 	//set zero flag if value is zero  
	if (value != 0) P &= 0xfd; 
	else P |= 0x02;	  
	//set negative flag if bit 8 set??? can this happen on an LSR?  
	if ((value & 0x80) == 0x80)P |= 0x80;	  
	else P &= 0x7f;		 
}

void lsra6502(void)
{
	P= (P & 0xfe) | (A & 0x01);
	A = A >>1;
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void nop6502(void)
{
}

void ora6502(void)
{
	opcodetable[opcode].adrmode();
 	A |= get6502memory(savepc);	   
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void pha6502(void)
{
 	put6502memory(0x100 + S-- , A);
}

void php6502(void)
{
	put6502memory(0x100 + S--, P);
}

void pla6502(void)
{
	A = get6502memory(++S + 0x100);
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void plp6502(void)
{
 	P = get6502memory(++S + 0x100) | 0x20;
}

void rol6502(void)
{
	saveflags=(P & 0x01);
	opcodetable[opcode].adrmode();
	value = get6502memory(savepc);
	P= (P & 0xfe) | ((value >>7) & 0x01);
	value = value << 1;
	value |= saveflags;
	put6502memory(savepc,value);
	if (value) P &= 0xfd; 
	else P |= 0x02;
	if (value & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void rola6502(void)
{
	saveflags=(P & 0x01);
	P= (P & 0xfe) | ((A >>7) & 0x01);
	A = A << 1;
	A |= saveflags;
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void ror6502(void)
{
	saveflags=(P & 0x01);
	opcodetable[opcode].adrmode();
 	value = get6502memory(savepc);
 	P= (P & 0xfe) | (value & 0x01);
	value = value >>1;
	if (saveflags) value |= 0x80;
	put6502memory(savepc,value);
	if (value) P &= 0xfd; 
	else P |= 0x02;
	if (value & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void rora6502(void)
{
	saveflags=(P & 0x01);
	P= (P & 0xfe) | (A & 0x01);
	A = A >>1;
	if (saveflags) A |= 0x80;
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void rti6502(void)
{										    
	P   = get6502memory(++S + 0x100)|0X20;
 	PC  = get6502memory(++S + 0x100);
	PC |= (get6502memory(++S + 0x100) << 8);
}

void rts6502(void)
{							    
	PC  = get6502memory(++S + 0x100);
	PC |= (get6502memory(++S + 0x100) << 8);
	PC++;
}

void sbc6502(void)
{
	opcodetable[opcode].adrmode();
	value = get6502memory(savepc) ^ 0xFF;
	saveflags=(P & 0x01);
	sum= ((char) A) + ((char) value) + (saveflags << 4);
	if ((sum>0x7f) || (sum<-0x80)) P |= 0x40; 
	else P &= 0xbf;
	sum= A + value + saveflags;
	if (sum>0xff) P |= 0x01; 
	else P &= 0xfe;
	A=sum;
	if (P & 0x08)
	{
		A -= 0x66;  
		P &= 0xfe;
		if ((A & 0x0f)>0x09)A += 0x06;	 
		if ((A & 0xf0)>0x90)
		{
			A += 0x60;
			P |= 0x01;
		}
	}
	else clockticks6502++;	   
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void sec6502(void)
{
	P |= 0x01;
}

void sed6502(void)
{
	P |= 0x08;
}

void sei6502(void)
{
	P |= 0x04;
}

void sta6502(void)
{
	opcodetable[opcode].adrmode();
	put6502memory(savepc,A);
}

void stx6502(void)
{
	opcodetable[opcode].adrmode();
	put6502memory(savepc,X);
}

void sty6502(void)
{
	opcodetable[opcode].adrmode();
	put6502memory(savepc,Y);
}

void tax6502(void)
{
	X=A;
	if (X) P &= 0xfd; 
	else P |= 0x02;
	if (X & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void tay6502(void)
{
	Y=A;
	if (Y) P &= 0xfd; 
	else P |= 0x02;
	if (Y & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void tsx6502(void)
{
	X=S;
	if (X) P &= 0xfd; 
	else P |= 0x02;
	if (X & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void txa6502(void)
{
	A=X;
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void txs6502(void)
{
      S=X;
}

void tya6502(void)
{
	A=Y;
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void bra6502(void)
{
	opcodetable[opcode].adrmode();
	PC += savepc;
	clockticks6502++;
}

void dea6502(void)
{
      A--;
      if (A) P &= 0xfd; 
	  else P |= 0x02;
      if (A & 0x80) P |= 0x80; 
	  else P &= 0x7f;
}

void ina6502(void)
{
	A++;
	if (A) P &= 0xfd; 
	else P |= 0x02;
	if (A & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void phx6502(void)
{
	put6502memory(0x100+S--,X);
}

void plx6502(void)
{							  
	X = get6502memory(++S + 0x100);
 	if (X) P &= 0xfd; 
	else P |= 0x02;
	if (X & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void phy6502(void)
{
	put6502memory(0x100+S--, Y);
}

void ply6502(void)
{
	Y = get6502memory(++S + 0x100);		  
	if (Y) P &= 0xfd; 
	else P |= 0x02;
	if (Y & 0x80) P |= 0x80; 
	else P &= 0x7f;
}

void stz6502(void)
{
	opcodetable[opcode].adrmode();
	put6502memory(savepc,0);
}

void tsb6502(void)
{
	u8 temp;	
 	opcodetable[opcode].adrmode();
 	temp  = get6502memory(savepc);
	temp |= A;
	put6502memory(savepc, temp);

	if(get6502memory(savepc))P &= 0xfd; 
	else P |= 0x02;
}

void trb6502(void)
{
	u8 temp;    	 
	opcodetable[opcode].adrmode();
 	temp  = get6502memory(savepc);
	temp &= (A ^ 0xFF);
	put6502memory(savepc, temp);    
	if(get6502memory(savepc))P &= 0xfd; 
	else P |= 0x02;
}

//
//	CPU复位与中断处理
//

//Reset CPU  
void reset6502(void)
{
	A=X=Y=P=0;
	P |= 0x20;		 //Z_FLAG | R_FLAG
	S=0xff;
	//PC  = get6502memory(0xfffc & addrmask);
	//PC |= get6502memory(0xfffd & addrmask) << 8;
	PC  = get6502memory(0xfffc);  //复位地址,从中读取PC
	PC |= get6502memory(0xfffd) << 8;
 	NMI_Flag = CLR0;
	IRQ_Flag = CLR0;
}

//Non maskerable interrupt  
void nmi6502(void)
{
	put6502memory(0x0100+S--,(BYTE)(PC>>8));
	put6502memory(0x0100+S--,(BYTE)(PC & 0xff));
	put6502memory(0x0100+S--,P);
	P |= 0x04;									   
	PC=get6502memory(0xfffa);
	PC |= get6502memory(0xfffb) << 8;
}

// Maskerable Interrupt 
void irq6502(void)
{
	put6502memory(0x0100+S--,(BYTE)(PC>>8));
	put6502memory(0x0100+S--,(BYTE)(PC & 0xff));
	put6502memory(0x0100+S--,P);
	P |= 0x04;									    
	PC=get6502memory(0xfffe);
	PC |= get6502memory(0xffff) << 8;
}

//
//执行指令
//

//Execute Instruction   
void exec6502(int timerTicks)
{
//	while (timerTicks > 0) 
//	{
//      	// fetch instruction
      opcode = gameImage[PC++];
//		opcode = get6502memory(PC);
//		PC++;
//
//		// execute instruction 用函数指针替代Switch改进执行效率的方法
//		opcodetable[opcode].instruction();
//		
//		// calculate clock cycles
//		clockticks6502 += opcodetable[opcode].ticks;
//		timerTicks -= clockticks6502;
//		clockticks6502 = 0;
//	}
   	//中断检测 
	if(NMI_Flag == SET1)
	{
		 nmi6502();
		 NMI_Flag = CLR0;
	}else
	{
	 	if(IRQ_Flag == SET1 && !(P & I_FLAG))
		{
			irq6502();
			IRQ_Flag = CLR0;
		}
	}   
	while (timerTicks > clockticks6502) 
	{
		opcode = get6502memory(PC);	  //读取6502存储器
		PC++;
		opcodetable[opcode].instruction();
		clockticks6502 += opcodetable[opcode].ticks;
	}
	clockticks6502 -= timerTicks;
}

//初始化6502 存储器 
void init6502mem( u8* exp_romptr,
				  u8* sramptr,			
				  u8* prg_rombank0ptr,		
			   	  u8  rom_num)		
{
	exp_rom		= exp_romptr;							//expansion rom 
	sram		= sramptr;								//sram 
	prg_rombank0= prg_rombank0ptr;						//prg-rom lower bank  
	prg_rombank1= prg_rombank0ptr +(0x4000*(rom_num-1));// prg-rom upper bank 

	clockticks6502 = 0;
}


#ifndef _6502_H_
#define _6502_H_
#include "type.h"
#include "PPU.h"	  
#include "joypad.h"

//Address mask. Atari Asteroids/Deluxe use 0x7fff -
//but use 0xffff for full 16 bit decode		 
//CPU中断标志
typedef enum {CLR0 = 0, SET1 = !CLR0} CPU_InitFlag;

extern  CPU_InitFlag NMI_Flag;
extern  CPU_InitFlag NMI_Flag;	   
//存储器指针 
extern u8* prg_rombank0;	//prg-rom lower bank 
extern u8* prg_rombank1;	//prg-rom upper bank 		   
//指令解释 
void implied6502(void);
void immediate6502(void);
void abs6502(void);
void relative6502(void);
void indirect6502(void);
void absx6502(void);
void absy6502(void);
void zp6502(void);
void zpx6502(void);
void zpy6502(void);
void indx6502(void);
void indy6502(void);
void indabsx6502(void);
void indzp6502(void);
void adc6502(void);
void and6502(void);
void asl6502(void);
void asla6502(void);
void bcc6502(void);
void bcs6502(void);
void beq6502(void);
void bit6502(void);
void bmi6502(void);
void bne6502(void);
void bpl6502(void);
void brk6502(void);
void bvc6502(void);
void bvs6502(void);
void clc6502(void);
void cld6502(void);
void cli6502(void);
void clv6502(void);
void cmp6502(void);
void cpx6502(void);
void cpy6502(void);
void dec6502(void);
void dex6502(void);
void dey6502(void);
void eor6502(void);
void inc6502(void);
void inx6502(void);
void iny6502(void);
void jmp6502(void);
void jsr6502(void);
void lda6502(void);
void ldx6502(void);
void ldy6502(void);
void lsr6502(void);
void lsra6502(void);
void nop6502(void);
void ora6502(void);
void pha6502(void);
void php6502(void);
void pla6502(void);
void plp6502(void);
void rol6502(void);
void rola6502(void);
void ror6502(void);
void rora6502(void);
void rti6502(void);
void rts6502(void);
void sbc6502(void);
void sec6502(void);
void sed6502(void);
void sei6502(void);
void sta6502(void);
void stx6502(void);
void sty6502(void);
void tax6502(void);
void tay6502(void);
void tsx6502(void);
void txa6502(void);
void txs6502(void);
void tya6502(void);
void bra6502(void);
void dea6502(void);
void ina6502(void);
void phx6502(void);
void plx6502(void);
void phy6502(void);
void ply6502(void);
void stz6502(void);
void tsb6502(void);
void trb6502(void);

//Non maskerable interrupt
void nmi6502(void);//不可屏蔽中断

//Maskerable Interrupt
void irq6502(void);//可屏蔽中断

//must be called first to initialise all 6502 engines arrays 
//初始化CPU RAM
void init6502mem(	u8* exp_romptr,
					u8* sramptr,			
					u8* prg_rombank0ptr,		
					u8  rom_num);

//sets all of the 6502 registers. The program counter is set from
//locations $FFFC and $FFFD masked with the above addrmask
void reset6502(void);

//run the 6502 engine for specified number of clock cycles
void exec6502(int timerTicks);

#endif	















  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 23:05:40  更:2021-12-28 23:10:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 15:37:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码