以为我会继续发布自己的实施方案。这是完全没有意义的,但这是一个完整的实现。
- 668行C.(不计算空白行或仅带有注释的行)
- 支持(我认为)所有未记录的说明。
- 支持BCD。
- CPU时钟周期计时。(包括对某些页面边界换行的调整)
- 可以单步执行或通过指定刻度数来执行指令。
- 支持在执行每条指令后挂接要调用的外部函数。这是因为它最初是用于NES模拟器的,而我将其用于音频定时。
/ * Fake6502 CPU仿真器核心v1.1 *******************
*(c)2011-2013 Mike Chambers *
****************************************************** *** /
#include <stdio.h>
#include <stdint.h>
//外部提供的功能
extern uint8_t read6502(uint16_t地址);
extern void write6502(uint16_t地址,uint8_t值);
// 6502定义
#define UNDOCUMENTED //定义后,将处理未记录的操作码。
//否则,它们将被简单地视为NOP。
//#define NES_CPU //定义后为二进制编码的十进制(BCD)
// ADC和SBC不接受状态标志。2A03
// Nintendo Entertainment System中的CPU不
//支持BCD操作。
#define FLAG_CARRY 0x01
#定义FLAG_ZERO 0x02
#定义FLAG_INTERRUPT 0x04
#定义FLAG_DECIMAL 0x08
#define FLAG_BREAK 0x10
#定义FLAG_CONSTANT 0x20
#定义FLAG_OVERFLOW 0x40
#define FLAG_SIGN 0x80
#定义BASE_STACK 0x100
#定义saveaccum(n)a =(uint8_t)((n)&0x00FF)
//标志修饰符宏
#define setcarry()状态| = FLAG_CARRY
#定义clearcarry()状态&=(〜FLAG_CARRY)
#define setzero()状态| = FLAG_ZERO
#定义clearzero()状态&=(〜FLAG_ZERO)
#define setinterrupt()状态| = FLAG_INTERRUPT
#定义clearinterrupt()状态和=(〜FLAG_INTERRUPT)
#define setdecimal()状态| = FLAG_DECIMAL
#定义cleardecimal()状态&=(〜FLAG_DECIMAL)
#define setoverflow()状态| = FLAG_OVERFLOW
#定义clearoverflow()状态&=(〜FLAG_OVERFLOW)
#define setsign()状态| = FLAG_SIGN
#定义clearsign()状态&=(〜FLAG_SIGN)
//标志计算宏
#定义zerocalc(n){\
如果((n)&0x00FF)clearzero(); \
否则setzero(); \
}
#define signcalc(n){\
如果((n)&0x0080)setsign(); \
否则clearsign(); \
}
#定义carrycalc(n){\
如果((n)&0xFF00)setcarry(); \
否则clearcarry(); \
}
#定义溢出计算(n,m,o){/ * n =结果,m =累加器,o =内存* / \
if((((n)^(uint16_t)(m))&((n)^(o))&0x0080)setoverflow(); \
否则clearoverflow(); \
}
// 6502 CPU寄存器
uint16_t pc;
uint8_t sp,a,x,y,status = FLAG_CONSTANT;
//辅助变量
uint64_t指令= 0; //跟踪执行的总指令
uint32_t clockticks6502 = 0,clockgoal6502 = 0;
uint16_t oldpc,ea,reladdr,值,结果;
uint8_t操作码,oldstatus;
//其他各种功能使用的一些通用功能
无效push16(uint16_t pushval){
write6502(BASE_STACK + sp,(pushval >> 8)&0xFF);
write6502(BASE_STACK +((sp-1)&0xFF),pushval&0xFF);
sp-= 2;
}
无效push8(uint8_t pushval){
write6502(BASE_STACK + sp--,pushval);
}
uint16_t pull16(){
uint16_t temp16;
temp16 = read6502(BASE_STACK +((sp + 1)和0xFF))| ((uint16_t)read6502(BASE_STACK +((sp + 2)和0xFF))<< 8);
sp + = 2;
return(temp16);
}
uint8_t pull8(){
返回(read6502(BASE_STACK + ++ sp));
}
无效reset6502(){
pc =(uint16_t)read6502(0xFFFC)| ((uint16_t)read6502(0xFFFD)<< 8);
a = 0;
x = 0;
y = 0;
sp = 0xFD;
状态| = FLAG_CONSTANT;
}
静态无效(* addrtable [256])();
静态void(* optable [256])();
uint8_t
//寻址模式功能,计算有效地址
静态void imp(){//暗示
}
静态void acc(){//累加器
}
静态void imm(){//立即
ea = pc ++;
}
static void zp(){//零页
ea =(uint16_t)read6502((uint16_t)pc ++);
}
静态void zpx(){//零页,X
ea =(((uint16_t)read6502((uint16_t)pc ++)+(uint16_t)x)&0xFF; //零页环绕
}
static void zpy(){//零页,Y
ea =(((uint16_t)read6502((uint16_t)pc ++)+(uint16_t)y)&0xFF; //零页环绕
}
static void rel(){//相对于分支操作(8位立即数,符号扩展)
reladdr =(uint16_t)read6502(pc ++);
如果(reladdr&0x80)reladdr | = 0xFF00;
}
静态无效abso(){//绝对
ea =(uint16_t)read6502(pc)| ((uint16_t)read6502(pc + 1)<< 8);
pc + = 2;
}
静态无效absx(){//绝对值,X
uint16_t起始页;
ea =(((uint16_t)read6502(pc)|((uint16_t)read6502(pc + 1)<< 8));
起始页= ea&0xFF00;
ea + =(uint16_t)x;
if(startpage!=(ea&0xFF00)){//在某些操作码上跨页的一个周期
刑罚= 1;
}
pc + = 2;
}
静态无效absy(){//绝对,Y
uint16_t起始页;
ea =(((uint16_t)read6502(pc)|((uint16_t)read6502(pc + 1)<< 8));
起始页= ea&0xFF00;
ea + =(uint16_t)y;
if(startpage!=(ea&0xFF00)){//在某些操作码上跨页的一个周期
刑罚= 1;
}
pc + = 2;
}
静态无效ind(){//间接
uint16_t eahelp,eahelp2;
eahelp =(uint16_t)read6502(pc)| (uint16_t)((uint16_t)read6502(pc + 1)<< 8);
eahelp2 =(eahelp&0xFF00)| ((eahelp + 1)&0x00FF); //复制6502页面边界环绕错误
ea =(uint16_t)read6502(eahelp)| (((uint16_t)read6502(eahelp2)<< 8);
pc + = 2;
}
静态无效indx(){//(间接,X)
uint16_t eahelp;
eahelp =(uint16_t)((((uint16_t)read6502(pc ++)+(uint16_t)x)和0xFF); //表指针的零页回绕
ea =(uint16_t)read6502(eahelp&0x00FF)| ((uint16_t)read6502((eahelp + 1)和0x00FF)<< 8);
}
静态无效indy(){//(间接),Y
uint16_t eahelp,eahelp2,起始页;
eahelp =(uint16_t)read6502(pc ++);
eahelp2 =(eahelp&0xFF00)| ((eahelp + 1)&0x00FF); //零页环绕
ea =(uint16_t)read6502(eahelp)| (((uint16_t)read6502(eahelp2)<< 8);
起始页= ea&0xFF00;
ea + =(uint16_t)y;
if(startpage!=(ea&0xFF00)){//在某些操作码上跨页的一个周期
刑罚= 1;
}
}
静态uint16_t getvalue(){
如果(addrtable [opcode] == acc)return((uint16_t)a);
否则return((uint16_t)read6502(ea));
}
静态无效值(uint16_t saveval){
如果(addrtable [opcode] == acc)a =(uint8_t)(saveval&0x00FF);
否则write6502(ea,(saveval&0x00FF));
}
//指令处理函数
静态void adc(){
刑罚= 1;
值= getvalue();
结果=(uint16_t)a +值+(uint16_t)(状态&FLAG_CARRY);
带进计算器(结果);
zerocalc(结果);
overflowcalc(result,a,value);
signcalc(结果);
#ifndef NES_CPU
如果(状态&FLAG_DECIMAL){
clearcarry();
如果((a&0x0F)> 0x09){
+ = 0x06;
}
如果((a&0xF0)> 0x90){
+ = 0x60;
setcarry();
}
clockticks6502 ++;
}
#万一
saveaccum(结果);
}
静态void和(){
刑罚= 1;
值= getvalue();
结果=(uint16_t)a&值;
zerocalc(结果);
signcalc(结果);
saveaccum(结果);
}
静态无效asl(){
值= getvalue();
结果=值<< 1;
带进计算器(结果);
zerocalc(结果);
signcalc(结果);
putvalue(结果);
}
静态void bcc(){
如果((状态&FLAG_CARRY)== 0){
oldpc = pc;
pc + = reladdr;
如果((oldpc&0xFF00)!=(pc&0xFF00))clockticks6502 + = 2; //检查跳转是否跨越页面边界
其他Clockticks6502 ++;
}
}
静态void bcs(){
如果((状态&FLAG_CARRY)== FLAG_CARRY){
oldpc = pc;
pc + = reladdr;
如果((oldpc&0xFF00)!=(pc&0xFF00))clockticks6502 + = 2; //检查跳转是否跨越页面边界
其他Clockticks6502 ++;
}
}
静态无效beq(){
如果((状态&FLAG_ZERO)== FLAG_ZERO){
oldpc = pc;
pc + = reladdr;
如果((oldpc&0xFF00)!=(pc&0xFF00))clockticks6502 + = 2; //检查跳转是否跨越页面边界
其他Clockticks6502 ++;
}
}
静态无效位(){
值= getvalue();
结果=(uint16_t)a&值;
zerocalc(结果);
状态=(状态&0x3F)| (uint8_t)(值&0xC0);
}
静态void bmi(){
如果((状态&FLAG_SIGN)== FLAG_SIGN){
oldpc = pc;
pc + = reladdr;
如果((oldpc&0xFF00)!=(pc&0xFF00))clockticks6502 + = 2; //检查跳转是否跨越页面边界
其他Clockticks6502 ++;
}
}
静态无效bne(){
如果((状态&FLAG_ZERO)== 0){
oldpc = pc;
pc + = reladdr;
如果((oldpc&0xFF00)!=(pc&0xFF00))clockticks6502 + = 2; //检查跳转是否跨越页面边界
其他Clockticks6502 ++;
}
}
静态无效bpl(){
如果((状态&FLAG_SIGN)== 0){
oldpc = pc;
pc + = reladdr;
如果((oldpc&0xFF00)!=(pc&0xFF00))clockticks6502 + = 2; //检查跳转是否跨越页面边界
其他Clockticks6502 ++;
}
}
静态void brk(){
pc ++;
push16(pc); //将下一条指令地址推入堆栈
push8(状态| FLAG_BREAK); //将CPU状态推送到堆栈
setinterrupt(); //设置中断标志
pc =(uint16_t)read6502(0xFFFE)| ((uint16_t)read6502(0xFFFF)<< 8);
}
静态void bvc(){
如果((状态&FLAG_OVERFLOW)== 0){
oldpc = pc;
pc + = reladdr;
如果((oldpc&0xFF00)!=(pc&0xFF00))clockticks6502 + = 2; //检查跳转是否跨越页面边界
其他Clockticks6502 ++;
}
}
静态无效bvs(){
如果((状态&FLAG_OVERFLOW)== FLAG_OVERFLOW){
oldpc = pc;
pc + = reladdr;
如果((oldpc&0xFF00)!=(pc&0xFF00))clockticks6502 + = 2; //检查跳转是否跨越页面边界
其他Clockticks6502 ++;
}
}
静态void clc(){
clearcarry();
}
静态void cld(){
cleardecimal();
}
静态void cli(){
clearinterrupt();
}
静态无效clv(){
clearoverflow();
}
静态无效cmp(){
刑罚= 1;
值= getvalue();
结果=(uint16_t)a-值;
如果(a> =(uint8_t)(value&0x00FF))setcarry();
否则clearcarry();
如果(a ==(uint8_t)(value&0x00FF))setzero();
否则clearzero();
signcalc(结果);
}
静态无效cpx(){
值= getvalue();
结果=(uint16_t)x-值;
如果(x> =(uint8_t)(value&0x00FF))setcarry();
否则clearcarry();
如果(x ==(uint8_t)(value&0x00FF))setzero();
否则clearzero();
signcalc(结果);
}
静态无效cpy(){
值= getvalue();
结果=(uint16_t)y-值;
如果(y> =(uint8_t)(value&0x00FF))setcarry();
否则clearcarry();
如果(y ==(uint8_t)(value&0x00FF))setzero();
否则clearzero();
signcalc(结果);
}
静态void dec(){
值= getvalue();
结果=值-1;
zerocalc(结果);
signcalc(结果);
putvalue(结果);
}
静态void dex(){
X - ;
zerocalc(x);
signcalc(x);
}
静态无效dey(){
y--;
zerocalc(y);
signcalc(y);
}
静态void eor(){
刑罚= 1;
值= getvalue();
结果=(uint16_t)一个^值;
zerocalc(结果);
signcalc(结果);
saveaccum(结果);
}
静态void inc(){
值= getvalue();
结果=值+ 1;
zerocalc(结果);
signcalc(结果);
putvalue(结果);
}
静态无效inx(){
x ++;
zerocalc(x);
signcalc(x);
}
静态无效iny(){
y ++;
zerocalc(y);
signcalc(y);
}
静态void jmp(){
pc = ea;
}
静态void jsr(){
push16(pc-1);
pc = ea;
}
静态void lda(){
刑罚= 1;
值= getvalue();
a =(uint8_t)(值&0x00FF);
zerocalc(a);
signcalc(a);
}
静态void ldx(){
刑罚= 1;
值= getvalue();
x =(uint8_t)(值&0x00FF);
zerocalc(x);
signcalc(x);
}
静态void ldy(){
刑罚= 1;
值= getvalue();
y =(uint8_t)(值&0x00FF);
zerocalc(y);
signcalc(y);
}
静态void lsr(){
值= getvalue();
结果=值>> 1;
如果(值&1)setcarry();
否则clearcarry();
zerocalc(结果);
signcalc(结果);
putvalue(结果);
}
静态无效nop(){
开关(操作码){
情况0x1C:
情况0x3C:
情况0x5C:
情况0x7C:
情况0xDC:
情况0xFC:
刑罚= 1;
打破;
}
}
静态无效ora(){
刑罚= 1;
值= getvalue();
结果=(uint16_t)a | 值;
zerocalc(结果);
signcalc(结果);
saveaccum(结果);
}
静态void pha(){
push8(a);
}
静态无效php(){
push8(状态| FLAG_BREAK);
}
静态void pla(){
一个= pull8();
zerocalc(a);
signcalc(a);
}
静态void plp(){
status = pull8() | FLAG_CONSTANT;
}
static void rol() {
value = getvalue();
result = (value << 1) | (status & FLAG_CARRY);
carrycalc(result);
zerocalc(result);
signcalc(result);
putvalue(result);
}
static void ror() {
value = getvalue();
result = (value >> 1) | ((status & FLAG_CARRY) << 7);
if (value & 1) setcarry();
else clearcarry();
zerocalc(result);
signcalc(result);
putvalue(result);
}
static void rti() {
status = pull8();
value = pull16();
pc = value;
}
static void rts() {
value = pull16();
pc = value + 1;
}
static void sbc() {
penaltyop = 1;
value = getvalue() ^ 0x00FF;
result = (uint16_t)a + value + (uint16_t)(status & FLAG_CARRY);
carrycalc(result);
zerocalc(result);
overflowcalc(result, a, value);
signcalc(result);
#ifndef NES_CPU
if (status & FLAG_DECIMAL) {
clearcarry();
a -= 0x66;
if ((a & 0x0F) > 0x09) {
a += 0x06;
}
if ((a & 0xF0) > 0x90) {
a += 0x60;
setcarry();
}
clockticks6502++;
}
#endif
saveaccum(result);
}
static void sec() {
setcarry();
}
static void sed() {
setdecimal();
}
static void sei() {
setinterrupt();
}
static void sta() {
putvalue(a);
}
static void stx() {
putvalue(x);
}
static void sty() {
putvalue(y);
}
static void tax() {
x = a;
zerocalc(x);
signcalc(x);
}
static void tay() {
y = a;
zerocalc(y);
signcalc(y);
}
static void tsx() {
x = sp;
zerocalc(x);
signcalc(x);
}
static void txa() {
a = x;
zerocalc(a);
signcalc(a);
}
static void txs() {
sp = x;
}
static void tya() {
a = y;
zerocalc(a);
signcalc(a);
}
//undocumented instructions
#ifdef UNDOCUMENTED
static void lax() {
lda();
ldx();
}
static void sax() {
sta();
stx();
putvalue(a & x);
if (penaltyop && penaltyaddr) clockticks6502--;
}
static void dcp() {
dec();
cmp();
if (penaltyop && penaltyaddr) clockticks6502--;
}
static void isb() {
inc();
sbc();
if (penaltyop && penaltyaddr) clockticks6502--;
}
static void slo() {
asl();
ora();
if (penaltyop && penaltyaddr) clockticks6502--;
}
static void rla() {
rol();
and();
if (penaltyop && penaltyaddr) clockticks6502--;
}
static void sre() {
lsr();
eor();
if (penaltyop && penaltyaddr) clockticks6502--;
}
static void rra() {
ror();
adc();
if (penaltyop && penaltyaddr) clockticks6502--;
}
#else
#define lax nop
#define sax nop
#define dcp nop
#define isb nop
#define slo nop
#define rla nop
#define sre nop
#define rra nop
#endif
static void (*addrtable[256])() = {
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
/* 0 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 0 */
/* 1 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 1 */
/* 2 */ abso, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 2 */
/* 3 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 3 */
/* 4 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 4 */
/* 5 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 5 */
/* 6 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, ind, abso, abso, abso, /* 6 */
/* 7 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 7 */
/* 8 */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* 8 */
/* 9 */ rel, indy, imp, indy, zpx, zpx, zpy, zpy, imp, absy, imp, absy, absx, absx, absy, absy, /* 9 */
/* A */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* A */
/* B */ rel, indy, imp, indy, zpx, zpx, zpy, zpy, imp, absy, imp, absy, absx, absx, absy, absy, /* B */
/* C */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* C */
/* D */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* D */
/* E */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* E */
/* F */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx /* F */
};
static void (*optable[256])() = {
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
/* 0 */ brk, ora, nop, slo, nop, ora, asl, slo, php, ora, asl, nop, nop, ora, asl, slo, /* 0 */
/* 1 */ bpl, ora, nop, slo, nop, ora, asl, slo, clc, ora, nop, slo, nop, ora, asl, slo, /* 1 */
/* 2 */ jsr, and, nop, rla, bit, and, rol, rla, plp, and, rol, nop, bit, and, rol, rla, /* 2 */
/* 3 */ bmi, and, nop, rla, nop, and, rol, rla, sec, and, nop, rla, nop, and, rol, rla, /* 3 */
/* 4 */ rti, eor, nop, sre, nop, eor, lsr, sre, pha, eor, lsr, nop, jmp, eor, lsr, sre, /* 4 */
/* 5 */ bvc, eor, nop, sre, nop, eor, lsr, sre, cli, eor, nop, sre, nop, eor, lsr, sre, /* 5 */
/* 6 */ rts, adc, nop, rra, nop, adc, ror, rra, pla, adc, ror, nop, jmp, adc, ror, rra, /* 6 */
/* 7 */ bvs, adc, nop, rra, nop, adc, ror, rra, sei, adc, nop, rra, nop, adc, ror, rra, /* 7 */
/* 8 */ nop, sta, nop, sax, sty, sta, stx, sax, dey, nop, txa, nop, sty, sta, stx, sax, /* 8 */
/* 9 */ bcc, sta, nop, nop, sty, sta, stx, sax, tya, sta, txs, nop, nop, sta, nop, nop, /* 9 */
/* A */ ldy, lda, ldx, lax, ldy, lda, ldx, lax, tay, lda, tax, nop, ldy, lda, ldx, lax, /* A */
/* B */ bcs, lda, nop, lax, ldy, lda, ldx, lax, clv, lda, tsx, lax, ldy, lda, ldx, lax, /* B */
/* C */ cpy, cmp, nop, dcp, cpy, cmp, dec, dcp, iny, cmp, dex, nop, cpy, cmp, dec, dcp, /* C */
/* D */ bne, cmp, nop, dcp, nop, cmp, dec, dcp, cld, cmp, nop, dcp, nop, cmp, dec, dcp, /* D */
/* E */ cpx, sbc, nop, isb, cpx, sbc, inc, isb, inx, sbc, nop, sbc, cpx, sbc, inc, isb, /* E */
/* F */ beq, sbc, nop, isb, nop, sbc, inc, isb, sed, sbc, nop, isb, nop, sbc, inc, isb /* F */
};
static const uint32_t ticktable[256] = {
/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */
/* 0 */ 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, /* 0 */
/* 1 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* 1 */
/* 2 */ 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6, /* 2 */
/* 3 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* 3 */
/* 4 */ 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6, /* 4 */
/* 5 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* 5 */
/* 6 */ 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6, /* 6 */
/* 7 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* 7 */
/* 8 */ 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, /* 8 */
/* 9 */ 2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5, /* 9 */
/* A */ 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, /* A */
/* B */ 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4, /* B */
/* C */ 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, /* C */
/* D */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* D */
/* E */ 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, /* E */
/* F */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7 /* F */
};
void nmi6502() {
push16(pc);
push8(status);
status |= FLAG_INTERRUPT;
pc = (uint16_t)read6502(0xFFFA) | ((uint16_t)read6502(0xFFFB) << 8);
}
void irq6502() {
push16(pc);
push8(status);
status |= FLAG_INTERRUPT;
pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8);
}
uint8_t callexternal = 0;
void (*loopexternal)();
void exec6502(uint32_t tickcount) {
clockgoal6502 += tickcount;
while (clockticks6502 < clockgoal6502) {
opcode = read6502(pc++);
penaltyop = 0;
penaltyaddr = 0;
(*addrtable[opcode])();
(*optable[opcode])();
clockticks6502 += ticktable[opcode];
if (penaltyop && penaltyaddr) clockticks6502++;
instructions++;
if (callexternal) (*loopexternal)();
}
}
void step6502() {
opcode = read6502(pc++);
penaltyop = 0;
penaltyaddr = 0;
(*addrtable[opcode])();
(*optable[opcode])();
clockticks6502 += ticktable[opcode];
if (penaltyop && penaltyaddr) clockticks6502++;
clockgoal6502 = clockticks6502;
instructions++;
if (callexternal) (*loopexternal)();
}
void hookexternal(void *funcptr) {
if (funcptr != (void *)NULL) {
loopexternal = funcptr;
callexternal = 1;
} else callexternal = 0;
}