Думал, что я пойду дальше и опубликую свою собственную реализацию. Это ПОЛНОСТЬЮ ungolfed, но это полная реализация.
- 668 строк C. (не считая пустых строк или строк только с комментариями)
- Поддерживает (я думаю) все недокументированные инструкции.
- Поддерживает BCD.
- Тактовая частота процессора. (включая корректировки для определенных обтеканий границ страницы)
- Может выполнять инструкции либо за один шаг, либо указав количество тиков.
- Поддерживает перехват внешней функции, которая вызывается после выполнения каждой инструкции. Это было, потому что это было первоначально для эмулятора NES, и я использовал это для синхронизации звука.
/ * Fake6502 Эмулятор процессора Core v1.1 *******************
* (c) 2011-2013 Майк Чемберс *
************************************************** *** /
#include <stdio.h>
#include <stdint.h>
// внешние функции
extern uint8_t read6502 (адрес uint16_t);
внешняя пустота write6502 (адрес uint16_t, значение uint8_t);
// 6502 определяет
#define UNDOCUMENTED // когда это определено, недокументированные коды операций обрабатываются.
// в противном случае они просто рассматриваются как NOP.
// # define NES_CPU // когда это определено, двоично-десятичное (BCD)
// флаг статуса не учитывается АЦП и СБК. 2A03
// Процессор в 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 () status | = FLAG_ZERO
#define clearzero () status & = (~ FLAG_ZERO)
#define setinterrupt () status | = FLAG_INTERRUPT
#define clearinterrupt () status & = (~ FLAG_INTERRUPT)
#define setdecimal () status | = FLAG_DECIMAL
#define cleardecimal () status & = (~ FLAG_DECIMAL)
#define setoverflow () status | = FLAG_OVERFLOW
#define clearoverflow () status & = (~ FLAG_OVERFLOW)
#define setsign () status | = FLAG_SIGN
#define clearsign () status & = (~ FLAG_SIGN)
// помечаем макросы
#define zerocalc (n) {\
if ((n) & 0x00FF) clearzero (); \
еще setzero (); \
}
#define signcalc (n) {\
if ((n) & 0x0080) setsign (); \
еще clearsign (); \
}
#define carrycalc (n) {\
if ((n) & 0xFF00) setcarry (); \
еще clearcarry (); \
}
#define overflowcalc (n, m, o) {/ * n = результат, m = аккумулятор, o = память * / \
if (((n) ^ (uint16_t) (m)) & ((n) ^ (o)) & 0x0080) setoverflow (); \
еще clearoverflow (); \
}
// 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, relddr, value, result;
код операции uint8_t, oldstatus;
// несколько общих функций, используемых различными другими функциями
void push16 (uint16_t pushval) {
write6502 (BASE_STACK + sp, (pushval >> 8) & 0xFF);
write6502 (BASE_STACK + ((sp - 1) & 0xFF), pushval & 0xFF);
sp - = 2;
}
void 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 () {
return (read6502 (BASE_STACK + ++ sp));
}
void reset6502 () {
pc = (uint16_t) read6502 (0xFFFC) | ((uint16_t) read6502 (0xFFFD) << 8);
а = 0;
х = 0;
у = 0;
sp = 0xFD;
статус | = FLAG_CONSTANT;
}
static void (* addrtable [256]) ();
static void (* optable [256]) ();
uint8_t наказание, пенальтидр;
// адресация функций режима, вычисление эффективных адресов
static void imp () {// подразумевается
}
static void acc () {// аккумулятор
}
static void imm () {// немедленно
ea = pc ++;
}
static void zp () {// нулевая страница
ea = (uint16_t) read6502 ((uint16_t) pc ++);
}
static 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 ++);
if (reladdr & 0x80) reladdr | = 0xFF00;
}
static void abso () {// абсолют
ea = (uint16_t) read6502 (шт) | ((uint16_t) read6502 (pc + 1) << 8);
pc + = 2;
}
static void 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;
}
static void 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;
}
static void 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;
}
static void 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);
}
static void 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;
}
}
static uint16_t getvalue () {
if (addrtable [opcode] == acc) return ((uint16_t) a);
еще возврат ((uint16_t) read6502 (ea));
}
static void putvalue (uint16_t saveval) {
if (addrtable [код операции] == acc) a = (uint8_t) (saveval & 0x00FF);
еще пишите 6502 (ea, (saveval & 0x00FF));
}
// функции обработчика команд
static void adc () {
неустойчивый = 1;
значение = getvalue ();
результат = (uint16_t) a + значение + (uint16_t) (статус & FLAG_CARRY);
carrycalc (результат);
zerocalc (результат);
overflowcalc (результат, a, значение);
signcalc (результат);
#ifndef NES_CPU
if (status & FLAG_DECIMAL) {
clearcarry ();
if ((a & 0x0F)> 0x09) {
+ = 0х06;
}
if ((a & 0xF0)> 0x90) {
+ = 0х60;
setcarry ();
}
clockticks6502 ++;
}
#endif
saveaccum (результат);
}
статическая пустота и () {
неустойчивый = 1;
значение = getvalue ();
результат = (uint16_t) a & значение;
zerocalc (результат);
signcalc (результат);
saveaccum (результат);
}
static void asl () {
значение = getvalue ();
результат = значение << 1;
carrycalc (результат);
zerocalc (результат);
signcalc (результат);
putvalue (результат);
}
static void bcc () {
if ((status & FLAG_CARRY) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // проверяем, перескочил ли переход границы страницы
остальное clockticks6502 ++;
}
}
static void bcs () {
if ((status & FLAG_CARRY) == FLAG_CARRY) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // проверяем, перескочил ли переход границы страницы
остальное clockticks6502 ++;
}
}
static void beq () {
if ((status & FLAG_ZERO) == FLAG_ZERO) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // проверяем, перескочил ли переход границы страницы
остальное clockticks6502 ++;
}
}
static void bit () {
значение = getvalue ();
результат = (uint16_t) a & значение;
zerocalc (результат);
status = (status & 0x3F) | (uint8_t) (значение & 0xC0);
}
static void bmi () {
if ((status & FLAG_SIGN) == FLAG_SIGN) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // проверяем, перескочил ли переход границы страницы
остальное clockticks6502 ++;
}
}
static void bne () {
if ((status & FLAG_ZERO) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // проверяем, перескочил ли переход границы страницы
остальное clockticks6502 ++;
}
}
static void bpl () {
if ((status & FLAG_SIGN) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // проверяем, перескочил ли переход границы страницы
остальное clockticks6502 ++;
}
}
static void brk () {
ПК ++;
push16 (ПК); // помещаем следующий адрес инструкции в стек
push8 (статус | FLAG_BREAK); // помещаем статус процессора в стек
setinterrupt (); // устанавливаем флаг прерывания
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; // проверяем, перескочил ли переход границы страницы
остальное clockticks6502 ++;
}
}
static void bvs () {
if ((status & FLAG_OVERFLOW) == FLAG_OVERFLOW) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // проверяем, перескочил ли переход границы страницы
остальное clockticks6502 ++;
}
}
static void clc () {
clearcarry ();
}
static void cld () {
cleardecimal ();
}
static void cli () {
clearinterrupt ();
}
static void clv () {
clearoverflow ();
}
static void cmp () {
неустойчивый = 1;
значение = getvalue ();
результат = (uint16_t) a - значение;
if (a> = (uint8_t) (value & 0x00FF)) setcarry ();
еще clearcarry ();
if (a == (uint8_t) (значение & 0x00FF)) setzero ();
остальное clearzero ();
signcalc (результат);
}
static void cpx () {
значение = getvalue ();
результат = (uint16_t) x - значение;
if (x> = (uint8_t) (значение & 0x00FF)) setcarry ();
еще clearcarry ();
if (x == (uint8_t) (значение & 0x00FF)) setzero ();
остальное clearzero ();
signcalc (результат);
}
static void cpy () {
значение = getvalue ();
результат = (uint16_t) y - значение;
if (y> = (uint8_t) (value & 0x00FF)) setcarry ();
еще clearcarry ();
if (y == (uint8_t) (value & 0x00FF)) setzero ();
остальное clearzero ();
signcalc (результат);
}
static void dec () {
значение = getvalue ();
результат = значение - 1;
zerocalc (результат);
signcalc (результат);
putvalue (результат);
}
static void dex () {
Икс--;
zerocalc (х);
signcalc (х);
}
static void dey () {
y--;
zerocalc (у);
signcalc (у);
}
static void eor () {
неустойчивый = 1;
значение = getvalue ();
результат = (uint16_t) значение ^;
zerocalc (результат);
signcalc (результат);
saveaccum (результат);
}
static void inc () {
значение = getvalue ();
результат = значение + 1;
zerocalc (результат);
signcalc (результат);
putvalue (результат);
}
static void inx () {
х ++;
zerocalc (х);
signcalc (х);
}
static void iny () {
у ++;
zerocalc (у);
signcalc (у);
}
static void jmp () {
pc = ea;
}
static void jsr () {
push16 (ПК - 1);
pc = ea;
}
static void lda () {
неустойчивый = 1;
значение = getvalue ();
a = (uint8_t) (значение & 0x00FF);
zerocalc (а);
signcalc (а);
}
static void ldx () {
неустойчивый = 1;
значение = getvalue ();
x = (uint8_t) (значение & 0x00FF);
zerocalc (х);
signcalc (х);
}
static void ldy () {
неустойчивый = 1;
значение = getvalue ();
y = (uint8_t) (значение & 0x00FF);
zerocalc (у);
signcalc (у);
}
static void lsr () {
значение = getvalue ();
результат = значение >> 1;
if (значение & 1) setcarry ();
еще clearcarry ();
zerocalc (результат);
signcalc (результат);
putvalue (результат);
}
static void nop () {
switch (код операции) {
случай 0x1C:
дело 0x3C:
дело 0x5C:
дело 0x7C:
случай 0xDC:
случай 0xFC:
неустойчивый = 1;
перемена;
}
}
static void ora () {
неустойчивый = 1;
значение = getvalue ();
результат = (uint16_t) a | ценность;
zerocalc (результат);
signcalc (результат);
saveaccum (результат);
}
static void pha () {
push8 (а);
}
static void php () {
push8 (статус | FLAG_BREAK);
}
static void pla () {
a = pull8 ();
zerocalc (а);
signcalc (а);
}
static void plp () {
status = pull8 () | FLAG_CONSTANT;
}
static void rol () {
значение = getvalue ();
результат = (значение << 1) | (статус & FLAG_CARRY);
carrycalc (результат);
zerocalc (результат);
signcalc (результат);
putvalue (результат);
}
static void ror () {
значение = getvalue ();
результат = (значение >> 1) | ((status & FLAG_CARRY) << 7);
if (значение & 1) setcarry ();
еще clearcarry ();
zerocalc (результат);
signcalc (результат);
putvalue (результат);
}
static void rti () {
status = pull8 ();
значение = pull16 ();
pc = значение;
}
static void rts () {
значение = pull16 ();
pc = значение + 1;
}
static void sbc () {
неустойчивый = 1;
значение = getvalue () ^ 0x00FF;
результат = (uint16_t) a + значение + (uint16_t) (статус & FLAG_CARRY);
carrycalc (результат);
zerocalc (результат);
overflowcalc (результат, a, значение);
signcalc (результат);
#ifndef NES_CPU
if (status & FLAG_DECIMAL) {
clearcarry ();
а - = 0х66;
if ((a & 0x0F)> 0x09) {
+ = 0х06;
}
if ((a & 0xF0)> 0x90) {
+ = 0х60;
setcarry ();
}
clockticks6502 ++;
}
#endif
saveaccum (результат);
}
static void sec () {
setcarry ();
}
static void sed () {
setdecimal ();
}
static void sei () {
setinterrupt ();
}
static void sta () {
putvalue (а);
}
static void stx () {
putvalue (х);
}
static void sty () {
putvalue (у);
}
статический недействительный налог () {
х = а;
zerocalc (х);
signcalc (х);
}
static void tay () {
у = а;
zerocalc (у);
signcalc (у);
}
static void tsx () {
х = сп;
zerocalc (х);
signcalc (х);
}
static void txa () {
а = х;
zerocalc (а);
signcalc (а);
}
static void txs () {
sp = x;
}
static void tya () {
а = у;
zerocalc (а);
signcalc (а);
}
// недокументированные инструкции
#ifdef UNDOCUMENTED
static void lax () {
Lda ();
LDX ();
}
static void sax () {
STA ();
STX ();
путвалюэ (а & х);
if (неустойчивый && puntiaddr) clockticks6502--;
}
static void dcp () {
Декабрь ();
CMP ();
if (неустойчивый && puntiaddr) clockticks6502--;
}
static void isb () {
вкл ();
SBC ();
if (неустойчивый && puntiaddr) clockticks6502--;
}
static void slo () {
над уровнем моря ();
ора ();
if (неустойчивый && puntiaddr) clockticks6502--;
}
static void rla () {
рол ();
а также();
if (неустойчивый && puntiaddr) clockticks6502--;
}
static void sre () {
LSR ();
ПНП ();
if (неустойчивый && puntiaddr) clockticks6502--;
}
static void rra () {
ROR ();
АЦП ();
if (неустойчивый && puntiaddr) 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 | Б | 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 | Б | 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, и, nop, rla, бит, и, rol, rla, plp, и, rol, nop, бит, и, rol, rla, / * 2 * /
/ * 3 * / bmi, и, nop, rla, nop, и, rol, rla, sec, и, nop, rla, nop, и, 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 | Б | C | D | E | F | * /
/ * 0 * / 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 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, 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, 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, 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, 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, 2, 4, 4, 4, 4, / * A * /
/ * B * / 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4, 4, / * B * /
/ * C * / 2, 6, 2, 8, 3, 3, 5, 5, 2, 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, 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 (ПК);
push8 (статус);
статус | = FLAG_INTERRUPT;
pc = (uint16_t) read6502 (0xFFFA) | ((uint16_t) read6502 (0xFFFB) << 8);
}
void irq6502 () {
push16 (ПК);
push8 (статус);
статус | = FLAG_INTERRUPT;
pc = (uint16_t) read6502 (0xFFFE) | ((uint16_t) read6502 (0xFFFF) << 8);
}
uint8_t callexternal = 0;
void (* loopexternal) ();
void exec6502 (uint32_t tickcount) {
clockgoal6502 + = счет тика;
while (clockticks6502 <clockgoal6502) {
код операции = read6502 (pc ++);
неустойчивый = 0;
неустойчивый = 0;
(* Addrtable [опкод]) ();
(* Optable [опкод]) ();
clockticks6502 + = ticktable [код операции];
if (неустойчивый && punadaddr) clockticks6502 ++;
инструкции ++;
if (callexternal) (* loopexternal) ();
}
}
void step6502 () {
код операции = read6502 (pc ++);
неустойчивый = 0;
неустойчивый = 0;
(* Addrtable [опкод]) ();
(* Optable [опкод]) ();
clockticks6502 + = ticktable [код операции];
if (неустойчивый && punadaddr) clockticks6502 ++;
clockgoal6502 = clockticks6502;
инструкции ++;
if (callexternal) (* loopexternal) ();
}
void hookexternal (void * funcptr) {
if (funcptr! = (void *) NULL) {
loopexternal = funcptr;
callexternal = 1;
} else callexternal = 0;
}