คิดว่าฉันจะไปข้างหน้าและโพสต์การดำเนินการของตัวเอง มันไม่สมบูรณ์อย่างสมบูรณ์ แต่เป็นการใช้งานอย่างเต็มรูปแบบ
- 668 บรรทัดของ C (ไม่นับบรรทัดว่างหรือบรรทัดที่มีความคิดเห็นเท่านั้น)
- รองรับ (ฉันคิดว่า) คำแนะนำที่ไม่มีเอกสารทั้งหมด
- รองรับ BCD
- รอบเวลาของนาฬิกา CPU (รวมถึงการปรับเปลี่ยนในการพันหน้ากระดาษ)
- สามารถดำเนินการตามคำสั่งได้ทั้งขั้นตอนเดียวหรือโดยการระบุจำนวนเห็บ
- รองรับการเชื่อมต่อฟังก์ชั่นภายนอกที่จะเรียกหลังจากการใช้งานทุกคำสั่ง นั่นเป็นเพราะในตอนแรกมันเป็นอีมูเลเตอร์ NES และฉันใช้มันเพื่อช่วงเวลาเสียง
/ * Fake6502 CPU emulator core v1.1 *********************
* (c) 2011-2013 Mike Chambers *
************************************************** *** /
#include <stdio.h>
#include <stdint.h>
// ฟังก์ชั่นที่ให้มาจากภายนอก
extern uint8_t read6502 (ที่อยู่ uint16_t);
เป็นโมฆะ extern เขียน 6502 (ที่อยู่ uint16_t ค่า uint8_t);
// 6502 กำหนด
#define UNDOCUMENTED // เมื่อมีการกำหนด opcodes ที่ไม่มีเอกสารจะได้รับการจัดการ
// มิฉะนั้นจะถือว่าเป็น NOP
// # define NES_CPU // เมื่อมีการกำหนดทศนิยมเลขฐานสอง (BCD)
// การตั้งค่าสถานะไม่ได้รับเกียรติจาก ADC และ SBC 2A03
// CPU ใน Nintendo Entertainment System ไม่ได้
// สนับสนุนการทำงาน BCD
#define FLAG_CARRY 0x01
#define FLAG_ZERO 0x02
#define FLAG_INTERRUPT 0x04
#define FLAG_DECIMAL 0x08
#define FLAG_BREAK 0x10
#define FLAG_CONSTANT 0x20
#define FLAG_OVERFLOW 0x40
#define FLAG_SIGN 0x80
#define BASE_STACK 0x100
#define saveaccum (n) a = (uint8_t) ((n) & 0x00FF)
// มาโครตัวปรับแต่งค่าสถานะ
#define setcarry () status | = FLAG_CARRY
#define clearcarry () status & = (~ FLAG_CARRY)
#define setzero () สถานะ | = FLAG_ZERO
#define clearzero () สถานะ & = (~ FLAG_ZERO)
#define setinterrupt () status | = FLAG_INTERRUPT
#define clearinterrupt () status & = (~ FLAG_INTERRUPT)
#define setdecimal () สถานะ | = FLAG_DECIMAL
#define cleardecimal () สถานะ & = (~ FLAG_DECIMAL)
#define setoverflow () สถานะ | = FLAG_OVERFLOW
#define clearoverflow () สถานะ & = (~ FLAG_OVERFLOW)
#define setsign () สถานะ | = FLAG_SIGN
#define clearsign () สถานะ & = (~ FLAG_SIGN)
// มาโครคำนวณธง
#define zerocalc (n) {\
ถ้า ((n) & 0x00FF) clearzero (); \
อื่น ๆ setzero (); \
}
#define signcalc (n) {\
ถ้า ((n) & 0x0080) setsign (); \
อื่น ๆ เคลียร์ (); \
}
#define carrycalc (n) {\
ถ้า ((n) & 0xFF00) setcarry (); \
อื่น clearcarry (); \
}
#define overflowcalc (n, m, o) {/ * n = ผล, m = ตัวสะสม, o = หน่วยความจำ * / \
ถ้า (((n) ^ (uint16_t) (m)) & ((n) ^ (o)) & 0x0080) setoverflow (); \
else clearoverflow (); \
}
// การลงทะเบียน CPU 6502
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, value, result;
uint8_t opcode, 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;
กลับ (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]) ();
โมฆะคงที่ (* optable [256]) ();
uint8_t เบี้ยปรับ, การลงโทษเพิ่ม;
// ฟังก์ชั่นโหมดที่อยู่คำนวณที่อยู่ที่มีประสิทธิภาพ
คงโมฆะแทตย์ () {// โดยนัย
}
static void acc () {// accumulator
}
โมฆะแบบคงที่ imm () {// ทันที
ea = pc ++;
}
โมฆะคง zp () {// ศูนย์หน้า
ea = (uint16_t) read6502 ((uint16_t) pc ++);
}
void คงที่ zpx () {// ศูนย์หน้า, X
ea = ((uint16_t) read6502 ((uint16_t) pc ++) + (uint16_t) x) & 0xFF; // การรวมหน้าศูนย์
}
void zpy แบบคงที่ () {// ศูนย์หน้า, Y
ea = ((uint16_t) read6502 ((uint16_t) pc ++) + (uint16_t) y) & 0xFF; // การรวมหน้าศูนย์
}
Static void rel () {// สัมพันธ์กับ ops ของสาขา (ค่าทันที 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));
startpage = ea & 0xFF00;
ea + = (uint16_t) x;
if (startpage! = (ea & 0xFF00)) {// หนึ่งรอบ penlty สำหรับการข้ามหน้าในบาง opcodes
เบี้ยปรับ = 1;
}
pc + = 2;
}
โมฆะคงที่ absy () {// แน่นอน, Y
uint16_t หน้าเริ่มต้น;
ea = ((uint16_t) read6502 (pc) | ((uint16_t) read6502 (pc + 1) << 8));
startpage = ea & 0xFF00;
ea + = (uint16_t) y;
if (startpage! = (ea & 0xFF00)) {// หนึ่งรอบ penlty สำหรับการข้ามหน้าในบาง opcodes
เบี้ยปรับ = 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);
}
โมฆะคงที่อินดี้ () {// (โดยอ้อม), 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);
startpage = ea & 0xFF00;
ea + = (uint16_t) y;
if (startpage! = (ea & 0xFF00)) {// หนึ่งรอบ penlty สำหรับการข้ามหน้าในบาง opcodes
เบี้ยปรับ = 1;
}
}
uint16_t คงที่ getvalue () {
if (addrtable [opcode] == acc) return ((uint16_t) a);
อื่นกลับมา ((uint16_t) read6502 (ea));
}
void putvalue แบบคงที่ (uint16_t saveval) {
if (addrtable [opcode] == acc) a = (uint8_t) (saveval & 0x00FF);
else write6502 (ea, (saveval & 0x00FF));
}
// ฟังก์ชันตัวจัดการคำสั่ง
คงโมฆะ adc () {
โทษ = 1;
value = getvalue ();
result = (uint16_t) a + value + (uint16_t) (สถานะ & FLAG_CARRY);
carrycalc (ผล);
zerocalc (ผล);
overflowcalc (ผลลัพธ์, a, value);
signcalc (ผล);
#ifndef NES_CPU
ถ้า (สถานะ & FLAG_DECIMAL) {
clearcarry ();
ถ้า ((& & 0x0F)> 0x09) {
a + = 0x06;
}
ถ้า ((& & 0xF0)> 0x90) {
+ = 0x60;
setcarry ();
}
clockticks6502 ++;
}
endif #
saveaccum (ผล);
}
โมฆะคงที่และ () {
โทษ = 1;
value = getvalue ();
result = (uint16_t) a & value;
zerocalc (ผล);
signcalc (ผล);
saveaccum (ผล);
}
โมฆะคง asl () {
value = getvalue ();
ผล = ค่า << 1;
carrycalc (ผล);
zerocalc (ผล);
signcalc (ผล);
putvalue (ผล);
}
โมฆะคง bcc () {
ถ้า ((สถานะ & FLAG_CARRY) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // ตรวจสอบว่ามีการข้ามขอบเขตเพจหรือไม่
อื่น clockticks6502 ++;
}
}
โมฆะคง bcs () {
ถ้า ((สถานะ & FLAG_CARRY) == FLAG_CARRY) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // ตรวจสอบว่ามีการข้ามขอบเขตเพจหรือไม่
อื่น clockticks6502 ++;
}
}
โมฆะคง beq () {
ถ้า ((สถานะ & FLAG_ZERO) == FLAG_ZERO) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // ตรวจสอบว่ามีการข้ามขอบเขตเพจหรือไม่
อื่น clockticks6502 ++;
}
}
บิตโมฆะคงที่ () {
value = getvalue ();
result = (uint16_t) a & value;
zerocalc (ผล);
สถานะ = (สถานะ & 0x3F) | (uint8_t) (ค่า & 0xC0);
}
โมฆะคง bmi () {
ถ้า ((สถานะ & FLAG_SIGN) == FLAG_SIGN) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // ตรวจสอบว่ามีการข้ามขอบเขตเพจหรือไม่
อื่น clockticks6502 ++;
}
}
โมฆะคง bne แบบคงที่ () {
ถ้า ((สถานะ & FLAG_ZERO) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // ตรวจสอบว่ามีการข้ามขอบเขตเพจหรือไม่
อื่น clockticks6502 ++;
}
}
โมฆะคง bpl () {
ถ้า ((สถานะ & FLAG_SIGN) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // ตรวจสอบว่ามีการข้ามขอบเขตเพจหรือไม่
อื่น clockticks6502 ++;
}
}
static void brk() {
pc++;
push16(pc); //push next instruction address onto stack
push8(status | FLAG_BREAK); //push CPU status to stack
setinterrupt(); //set interrupt flag
pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8);
}
static void bvc() {
if ((status & FLAG_OVERFLOW) == 0) {
oldpc = pc;
pc += reladdr;
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
else clockticks6502++;
}
}
static void bvs() {
if ((status & FLAG_OVERFLOW) == FLAG_OVERFLOW) {
oldpc = pc;
pc += reladdr;
if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
else clockticks6502++;
}
}
static void clc() {
clearcarry();
}
static void cld() {
cleardecimal();
}
static void cli() {
clearinterrupt();
}
static void clv() {
clearoverflow();
}
static void cmp() {
penaltyop = 1;
value = getvalue();
result = (uint16_t)a - value;
if (a >= (uint8_t)(value & 0x00FF)) setcarry();
else clearcarry();
if (a == (uint8_t)(value & 0x00FF)) setzero();
else clearzero();
signcalc(result);
}
static void cpx() {
value = getvalue();
result = (uint16_t)x - value;
if (x >= (uint8_t)(value & 0x00FF)) setcarry();
else clearcarry();
if (x == (uint8_t)(value & 0x00FF)) setzero();
else clearzero();
signcalc(result);
}
static void cpy() {
value = getvalue();
result = (uint16_t)y - value;
if (y >= (uint8_t)(value & 0x00FF)) setcarry();
else clearcarry();
if (y == (uint8_t)(value & 0x00FF)) setzero();
else clearzero();
signcalc(result);
}
static void dec() {
value = getvalue();
result = value - 1;
zerocalc(result);
signcalc(result);
putvalue(result);
}
static void dex() {
x--;
zerocalc(x);
signcalc(x);
}
static void dey() {
y--;
zerocalc(y);
signcalc(y);
}
static void eor() {
penaltyop = 1;
value = getvalue();
result = (uint16_t)a ^ value;
zerocalc(result);
signcalc(result);
saveaccum(result);
}
static void inc() {
value = getvalue();
result = value + 1;
zerocalc(result);
signcalc(result);
putvalue(result);
}
static void inx() {
x++;
zerocalc(x);
signcalc(x);
}
static void iny() {
y++;
zerocalc(y);
signcalc(y);
}
static void jmp() {
pc = ea;
}
static void jsr() {
push16(pc - 1);
pc = ea;
}
static void lda() {
penaltyop = 1;
value = getvalue();
a = (uint8_t)(value & 0x00FF);
zerocalc(a);
signcalc(a);
}
static void ldx() {
penaltyop = 1;
value = getvalue();
x = (uint8_t)(value & 0x00FF);
zerocalc(x);
signcalc(x);
}
static void ldy() {
penaltyop = 1;
value = getvalue();
y = (uint8_t)(value & 0x00FF);
zerocalc(y);
signcalc(y);
}
static void lsr() {
value = getvalue();
result = value >> 1;
if (value & 1) setcarry();
else clearcarry();
zerocalc(result);
signcalc(result);
putvalue(result);
}
static void nop() {
switch (opcode) {
case 0x1C:
case 0x3C:
case 0x5C:
case 0x7C:
case 0xDC:
case 0xFC:
penaltyop = 1;
break;
}
}
static void ora() {
penaltyop = 1;
value = getvalue();
result = (uint16_t)a | value;
zerocalc(result);
signcalc(result);
saveaccum(result);
}
static void pha() {
push8(a);
}
static void php() {
push8(status | FLAG_BREAK);
}
static void pla() {
a = pull8();
zerocalc(a);
signcalc(a);
}
static 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;
}