Pensé en seguir adelante y publicar mi propia implementación. Está COMPLETAMENTE sin golf, pero es una implementación completa.
- 668 líneas de C. (sin contar líneas en blanco o líneas con solo comentarios)
- Admite (creo) todas las instrucciones no documentadas.
- Soporta BCD.
- Tiempo de ciclo del reloj de la CPU. (incluidos los ajustes en ciertas envolturas de límite de página)
- Puede ejecutar instrucciones ya sea en un solo paso o especificando el número de ticks.
- Admite el enganche de una función externa que se llamará después de que se ejecute cada instrucción. Esto se debió a que originalmente era para un emulador NES y lo usé para la sincronización de audio.
/ * Fake6502 CPU emulator core v1.1 *******************
* (c) 2011-2013 Mike Chambers *
************************************************** *** /
#include <stdio.h>
#include <stdint.h>
// funciones suministradas externamente
utern8_t externo read6502 (dirección uint16_t);
extern void write6502 (dirección uint16_t, valor uint8_t);
// 6502 define
#define UNDOCUMENTED // cuando se define esto, se manejan códigos de operación no documentados.
// de lo contrario, simplemente se tratan como NOP.
// # define NES_CPU // cuando está definido, el decimal codificado en binario (BCD)
// el indicador de estado no es aceptado por ADC y SBC. el 2A03
// CPU en el sistema de entretenimiento de Nintendo no
// admite la operación 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)
// macros modificadoras de bandera
#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)
// macros de cálculo de marca
#define zerocalc (n) {\
if ((n) & 0x00FF) clearzero (); \
else setzero (); \
}
#define signcalc (n) {\
if ((n) & 0x0080) setsign (); \
else clearsign (); \
}
#define carrycalc (n) {\
if ((n) & 0xFF00) setcarry (); \
else clearcarry (); \
}
#define overflowcalc (n, m, o) {/ * n = resultado, m = acumulador, o = memoria * / \
if (((n) ^ (uint16_t) (m)) & ((n) ^ (o)) & 0x0080) setoverflow (); \
más clearoverflow (); \
}
// 6502 registros de CPU
uint16_t pc;
uint8_t sp, a, x, y, estado = FLAG_CONSTANT;
// variables auxiliares
uint64_t instrucciones = 0; // realiza un seguimiento del total de instrucciones ejecutadas
uint32_t clockticks6502 = 0, clockgoal6502 = 0;
uint16_t oldpc, ea, reladdr, valor, resultado;
uint8_t opcode, oldstatus;
// algunas funciones generales utilizadas por otras funciones
vacío push16 (uint16_t pushval) {
write6502 (BASE_STACK + sp, (pushval >> 8) & 0xFF);
write6502 (BASE_STACK + ((sp - 1) & 0xFF), pushval & 0xFF);
sp - = 2;
}
vacío 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;
retorno (temp16);
}
uint8_t pull8 () {
return (read6502 (BASE_STACK + ++ sp));
}
anular reset6502 () {
pc = (uint16_t) read6502 (0xFFFC) | ((uint16_t) read6502 (0xFFFD) << 8);
a = 0;
x = 0;
y = 0;
sp = 0xFD;
estado | = FLAG_CONSTANT;
}
vacío estático (* addrtable [256]) ();
vacío estático (* optable [256]) ();
uint8_t penaop, penaaddr;
// funciones de modo de direccionamiento, calcula direcciones efectivas
static void imp () {// implícito
}
static void acc () {// acumulador
}
static void imm () {// inmediato
ea = pc ++;
}
static void zp () {// página cero
ea = (uint16_t) read6502 ((uint16_t) pc ++);
}
static void zpx () {// página cero, X
ea = ((uint16_t) read6502 ((uint16_t) pc ++) + (uint16_t) x) & 0xFF; // envolvente de página cero
}
static void zpy () {// página cero, Y
ea = ((uint16_t) read6502 ((uint16_t) pc ++) + (uint16_t) y) & 0xFF; // envolvente de página cero
}
static void rel () {// relativo para operaciones de bifurcación (valor inmediato de 8 bits, signo extendido)
reladdr = (uint16_t) read6502 (pc ++);
if (reladdr & 0x80) reladdr | = 0xFF00;
}
estático vacío abso () {// absoluto
ea = (uint16_t) read6502 (pc) | ((uint16_t) read6502 (pc + 1) << 8);
pc + = 2;
}
estático vacío absx () {// absoluto, X
uint16_t página de inicio;
ea = ((uint16_t) read6502 (pc) | ((uint16_t) read6502 (pc + 1) << 8));
startpage = ea & 0xFF00;
ea + = (uint16_t) x;
if (startpage! = (ea & 0xFF00)) {// un ciclo de penilty para cruzar páginas en algunos códigos de operación
penaaddr = 1;
}
pc + = 2;
}
absy vacío estático () {// absoluto, Y
uint16_t página de inicio;
ea = ((uint16_t) read6502 (pc) | ((uint16_t) read6502 (pc + 1) << 8));
startpage = ea & 0xFF00;
ea + = (uint16_t) y;
if (startpage! = (ea & 0xFF00)) {// un ciclo de penilty para cruzar páginas en algunos códigos de operación
penaaddr = 1;
}
pc + = 2;
}
static void ind () {// indirecto
uint16_t eahelp, eahelp2;
eahelp = (uint16_t) read6502 (pc) | (uint16_t) ((uint16_t) read6502 (pc + 1) << 8);
eahelp2 = (eahelp y 0xFF00) | ((eahelp + 1) y 0x00FF); // replicar el error envolvente del límite de página 6502
ea = (uint16_t) read6502 (eahelp) | ((uint16_t) read6502 (eahelp2) << 8);
pc + = 2;
}
estático vacío indx () {// (indirecto, X)
uint16_t eahelp;
eahelp = (uint16_t) (((uint16_t) read6502 (pc ++) + (uint16_t) x) & 0xFF); // ajuste de página cero para puntero de tabla
ea = (uint16_t) read6502 (eahelp & 0x00FF) | ((uint16_t) read6502 ((eahelp + 1) & 0x00FF) << 8);
}
estático vacío indy () {// (indirecto), Y
uint16_t eahelp, eahelp2, página de inicio;
eahelp = (uint16_t) read6502 (pc ++);
eahelp2 = (eahelp y 0xFF00) | ((eahelp + 1) y 0x00FF); // envolvente de página cero
ea = (uint16_t) read6502 (eahelp) | ((uint16_t) read6502 (eahelp2) << 8);
startpage = ea & 0xFF00;
ea + = (uint16_t) y;
if (startpage! = (ea & 0xFF00)) {// un ciclo de penilty para cruzar páginas en algunos códigos de operación
penaaddr = 1;
}
}
static uint16_t getvalue () {
if (addrtable [opcode] == acc) return ((uint16_t) a);
else return ((uint16_t) read6502 (ea));
}
valor de valor vacío estático (uint16_t saveval) {
if (addrtable [opcode] == acc) a = (uint8_t) (saveval & 0x00FF);
de lo contrario, escriba 6502 (ea, (saveval & 0x00FF));
}
// funciones del manejador de instrucciones
adc vacío estático () {
pena = 1;
valor = getvalue ();
resultado = (uint16_t) a + valor + (uint16_t) (estado & FLAG_CARRY);
carrycalc (resultado);
zerocalc (resultado);
overflowcalc (resultado, a, valor);
signcalc (resultado);
#ifndef NES_CPU
if (estado y FLAG_DECIMAL) {
clearcarry ();
if ((a & 0x0F)> 0x09) {
a + = 0x06;
}
if ((a & 0xF0)> 0x90) {
a + = 0x60;
setcarry ();
}
clockticks6502 ++;
}
#terminara si
saveaccum (resultado);
}
vacío estático y () {
pena = 1;
valor = getvalue ();
resultado = (uint16_t) un & valor;
zerocalc (resultado);
signcalc (resultado);
saveaccum (resultado);
}
estático vacío asl () {
valor = getvalue ();
resultado = valor << 1;
carrycalc (resultado);
zerocalc (resultado);
signcalc (resultado);
putvalue (resultado);
}
vacío estático bcc () {
if ((estado y FLAG_CARRY) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // verifica si el salto cruzó el límite de una página
de lo contrario clockticks6502 ++;
}
}
vacío estático bcs () {
if ((estado y FLAG_CARRY) == FLAG_CARRY) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // verifica si el salto cruzó el límite de una página
de lo contrario clockticks6502 ++;
}
}
estático vacío beq () {
if ((estado y FLAG_ZERO) == FLAG_ZERO) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // verifica si el salto cruzó el límite de una página
de lo contrario clockticks6502 ++;
}
}
bit vacío estático () {
valor = getvalue ();
resultado = (uint16_t) un & valor;
zerocalc (resultado);
estado = (estado y 0x3F) | (uint8_t) (valor & 0xC0);
}
vacío estático bmi () {
if ((estado y FLAG_SIGN) == FLAG_SIGN) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // verifica si el salto cruzó el límite de una página
de lo contrario clockticks6502 ++;
}
}
vacío estático bne () {
if ((estado y FLAG_ZERO) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // verifica si el salto cruzó el límite de una página
de lo contrario clockticks6502 ++;
}
}
estático vacío bpl () {
if ((estado y FLAG_SIGN) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // verifica si el salto cruzó el límite de una página
de lo contrario clockticks6502 ++;
}
}
vacío estático brk () {
pc ++;
push16 (pc); // inserta la siguiente dirección de instrucciones en la pila
push8 (estado | FLAG_BREAK); // empujar el estado de la CPU para apilar
setinterrupt (); // establecer bandera de interrupción
pc = (uint16_t) read6502 (0xFFFE) | ((uint16_t) read6502 (0xFFFF) << 8);
}
estático vacío bvc () {
if ((estado y FLAG_OVERFLOW) == 0) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // verifica si el salto cruzó el límite de una página
de lo contrario clockticks6502 ++;
}
}
vacío estático bvs () {
if ((estado y FLAG_OVERFLOW) == FLAG_OVERFLOW) {
oldpc = pc;
pc + = reladdr;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // verifica si el salto cruzó el límite de una página
de lo contrario clockticks6502 ++;
}
}
vacío estático clc () {
clearcarry ();
}
static void cld () {
cleardecimal ();
}
vacío estático cli () {
clearinterrupt ();
}
static void clv () {
clearoverflow ();
}
vacío vacío cmp () {
pena = 1;
valor = getvalue ();
resultado = (uint16_t) a - valor;
if (a> = (uint8_t) (valor & 0x00FF)) setcarry ();
sino clearcarry ();
if (a == (uint8_t) (valor & 0x00FF)) setzero ();
más clearzero ();
signcalc (resultado);
}
estático vacío cpx () {
valor = getvalue ();
resultado = (uint16_t) x - valor;
if (x> = (uint8_t) (valor & 0x00FF)) setcarry ();
sino clearcarry ();
if (x == (uint8_t) (valor & 0x00FF)) setzero ();
más clearzero ();
signcalc (resultado);
}
estático vacío cpy () {
valor = getvalue ();
resultado = (uint16_t) y - valor;
if (y> = (uint8_t) (valor & 0x00FF)) setcarry ();
sino clearcarry ();
if (y == (uint8_t) (valor & 0x00FF)) setzero ();
más clearzero ();
signcalc (resultado);
}
vacío estático dec () {
valor = getvalue ();
resultado = valor - 1;
zerocalc (resultado);
signcalc (resultado);
putvalue (resultado);
}
dex vacío estático () {
X--;
zerocalc (x);
Signcalc (x);
}
vacío estático dey () {
y--;
zerocalc (y);
signcalc (y);
}
vacío estático eor () {
pena = 1;
valor = getvalue ();
resultado = (uint16_t) un valor ^;
zerocalc (resultado);
signcalc (resultado);
saveaccum (resultado);
}
static void inc () {
valor = getvalue ();
resultado = valor + 1;
zerocalc (resultado);
signcalc (resultado);
putvalue (resultado);
}
vacío estático inx () {
x ++;
zerocalc (x);
Signcalc (x);
}
vacío estático iny () {
y ++;
zerocalc (y);
signcalc (y);
}
jmp vacío estático () {
pc = ea;
}
estático vacío jsr () {
push16 (pc - 1);
pc = ea;
}
vacío estático lda () {
pena = 1;
valor = getvalue ();
a = (uint8_t) (valor & 0x00FF);
zerocalc (a);
Signcalc (a);
}
estático vacío ldx () {
pena = 1;
valor = getvalue ();
x = (uint8_t) (valor & 0x00FF);
zerocalc (x);
Signcalc (x);
}
estático vacío ldy () {
pena = 1;
valor = getvalue ();
y = (uint8_t) (valor & 0x00FF);
zerocalc (y);
signcalc (y);
}
estático vacío lsr () {
valor = getvalue ();
resultado = valor >> 1;
if (valor & 1) setcarry ();
sino clearcarry ();
zerocalc (resultado);
signcalc (resultado);
putvalue (resultado);
}
vacío estático nop () {
interruptor (código de operación) {
caso 0x1C:
caso 0x3C:
caso 0x5C:
caso 0x7C:
caso 0xDC:
caso 0xFC:
pena = 1;
descanso;
}
}
vacío estático ora () {
pena = 1;
valor = getvalue ();
resultado = (uint16_t) a | valor;
zerocalc (resultado);
signcalc (resultado);
saveaccum (resultado);
}
pha vacío estático () {
push8 (a);
}
php vacío estático () {
push8 (estado | FLAG_BREAK);
}
vacío estático pla () {
a = pull8 ();
zerocalc (a);
Signcalc (a);
}
vacío estático plp () {
estado = pull8 () | FLAG_CONSTANT;
}
rol vacío estático () {
valor = getvalue ();
resultado = (valor << 1) | (estado y FLAG_CARRY);
carrycalc (resultado);
zerocalc (resultado);
signcalc (resultado);
putvalue (resultado);
}
vacío estático ror () {
valor = getvalue ();
resultado = (valor >> 1) | ((estado y FLAG_CARRY) << 7);
if (valor & 1) setcarry ();
sino clearcarry ();
zerocalc (resultado);
signcalc (resultado);
putvalue (resultado);
}
estático vacío rti () {
estado = pull8 ();
valor = pull16 ();
pc = valor;
}
estático vacío rts () {
valor = pull16 ();
pc = valor + 1;
}
estático vacío sbc () {
pena = 1;
valor = getvalue () ^ 0x00FF;
resultado = (uint16_t) a + valor + (uint16_t) (estado & FLAG_CARRY);
carrycalc (resultado);
zerocalc (resultado);
overflowcalc (resultado, a, valor);
signcalc (resultado);
#ifndef NES_CPU
if (estado y FLAG_DECIMAL) {
clearcarry ();
a - = 0x66;
if ((a & 0x0F)> 0x09) {
a + = 0x06;
}
if ((a & 0xF0)> 0x90) {
a + = 0x60;
setcarry ();
}
clockticks6502 ++;
}
#terminara si
saveaccum (resultado);
}
sec vacío vacío () {
setcarry ();
}
vacío estático sed () {
setdecimal ();
}
vacío estático sei () {
setinterrupt ();
}
vacío estático sta () {
valor de valoración (a);
}
estático vacío stx () {
valor de put (x);
}
sty vacío vacío () {
valor de venta (y);
}
impuesto nulo estático () {
x = a;
zerocalc (x);
Signcalc (x);
}
vacío estático tay () {
y = a;
zerocalc (y);
signcalc (y);
}
vacío estático tsx () {
x = sp;
zerocalc (x);
Signcalc (x);
}
txa vacío estático () {
a = x;
zerocalc (a);
Signcalc (a);
}
txs de vacío estático () {
sp = x;
}
tya vacío estático () {
a = y;
zerocalc (a);
Signcalc (a);
}
// instrucciones no documentadas
#ifdef INOCENTADO
vacío estático lax () {
lda ();
ldx ();
}
saxo vacío estático () {
sta ();
stx ();
putvalue (a & x);
if (penalización && penalizaciónaddr) clockticks6502--;
}
DCP vacío estático () {
dic();
cmp ();
if (penalización && penalizaciónaddr) clockticks6502--;
}
isb vacío estático () {
Cía();
sbc ();
if (penalización && penalizaciónaddr) clockticks6502--;
}
vacío estático slo () {
asl ();
ora ();
if (penalización && penalizaciónaddr) clockticks6502--;
}
estático vacío rla () {
rol ();
y();
if (penalización && penalizaciónaddr) clockticks6502--;
}
estático vacío sre () {
lsr ();
eor ();
if (penalización && penalizaciónaddr) clockticks6502--;
}
vacío estático rra () {
ror ();
adc ();
if (penalización && penalizaciónaddr) clockticks6502--;
}
#más
#define lax nop
#definir sax nop
#define dcp nop
#define isb nop
#define slo nop
#define rla nop
#define sre nop
#define rra nop
#terminara si
vacío estático (* 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 * /
};
vacío estático (* 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, y, nop, rla, bit, y, rol, rla, plp, y, rol, nop, bit, y, rol, rla, / * 2 * /
/ * 3 * / bmi, y, nop, rla, nop, y, rol, rla, sec, y, nop, rla, nop, y, 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 * /
};
tabla estática 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 * /
};
nmi6502 nulo () {
push16 (pc);
push8 (estado);
estado | = FLAG_INTERRUPT;
pc = (uint16_t) read6502 (0xFFFA) | ((uint16_t) read6502 (0xFFFB) << 8);
}
nulo irq6502 () {
push16 (pc);
push8 (estado);
estado | = FLAG_INTERRUPT;
pc = (uint16_t) read6502 (0xFFFE) | ((uint16_t) read6502 (0xFFFF) << 8);
}
uint8_t callexternal = 0;
nulo (* loopexternal) ();
exec6502 nulo (tintcount uint32_t) {
clockgoal6502 + = tickcount;
while (clockticks6502 <clockgoal6502) {
opcode = read6502 (pc ++);
pena = 0;
penaaddr = 0;
(* addrtable [código de operación]) ();
(* optable [opcode]) ();
clockticks6502 + = ticktable [código de operación];
if (penalización & y penalizaciónaddr) clockticks6502 ++;
instrucciones ++;
if (callexternal) (* loopexternal) ();
}
}
nulo step6502 () {
opcode = read6502 (pc ++);
pena = 0;
penaaddr = 0;
(* addrtable [código de operación]) ();
(* optable [opcode]) ();
clockticks6502 + = ticktable [código de operación];
if (castigo & & castigoaddr) tics de reloj
clockgoal6502 = clockticks6502;
instrucciones ++;
if (callexternal) (* loopexternal) ();
}
vacío hookexternal (vacío * funcptr) {
if (funcptr! = (void *) NULL) {
loopexternal = funcptr;
callexternal = 1;
} más callexternal = 0;
}