계속해서 내 구현을 게시 할 것이라고 생각했습니다. 완벽하게 ungolfed이지만 전체 구현입니다.
- C의 668 줄 (빈 줄이나 주석 만있는 줄은 제외)
- 문서화되지 않은 모든 지침을 지원합니다.
- 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 // 이가 정의되면 문서화되지 않은 opcode가 처리됩니다.
// 그렇지 않으면 단순히 NOP로 취급됩니다.
// # define NES_CPU // 이것이 정의 될 때, 이진 코드 10 진수 (BCD)
// 상태 플래그는 ADC 및 SBC에서 인정하지 않습니다. 2A03
// 닌텐도 엔터테인먼트 시스템의 CPU는
// 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
#BASE_STACK 0x100 정의
# saveaccum (n) a = (uint8_t) ((n) & 0x00FF) 정의
// 플래그 수정 자 매크로
#define setcarry () status | = FLAG_CARRY
#clearcarry () 상태 정의 & = (~ FLAG_CARRY)
#define setzero () status | = FLAG_ZERO
#clearzero () 상태 정의 & = (~ FLAG_ZERO)
#define setinterrupt () status | = FLAG_INTERRUPT
#define clearinterrupt () 상태 & = (~ FLAG_INTERRUPT)
#define setdecimal () 상태 | = FLAG_DECIMAL
#define cleardecimal () 상태 & = (~ FLAG_DECIMAL)
#define setoverflow () 상태 | = FLAG_OVERFLOW
#define clearoverflow () 상태 & = (~ FLAG_OVERFLOW)
#define setsign () status | = FLAG_SIGN
#define clearsign () 상태 & = (~ FLAG_SIGN)
// 플래그 계산 매크로
#zerocalc (n) 정의 {\
if ((n) & 0x00FF) clearzero (); \
그렇지 않으면 setzero (); \
}
#define signcalc (n) {\
if ((n) & 0x0080) setsign (); \
그렇지 않으면 clearsign (); \
}
# carrycalc (n) 정의 {\
if ((n) & 0xFF00) setcarry (); \
그렇지 않으면 clearcarry (); \
}
# 정의 overflowcalc (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, 상태 = FLAG_CONSTANT;
// 도우미 변수
uint64_t 명령 = 0; // 실행 된 총 명령 추적
uint32_t clockticks6502 = 0, clockgoal6502 = 0;
uint16_t oldpc, ea, reladdr, 가치, 결과;
uint8_t opcode, oldstatus;
// 다양한 다른 함수에서 사용되는 몇 가지 일반적인 함수
void push16 (uint16_t pushval) {
쓰기 6502 (BASE_STACK + sp, (pushval >> 8) & 0xFF);
write6502 (BASE_STACK + ((sp -1) & 0xFF), 푸시 발 & 0xFF);
sp-= 2;
}
void push8 (uint8_t pushval) {
write6502 (BASE_STACK + sp--, 푸시 발);
}
uint16_t pull16 () {
uint16_t temp16;
temp16 = 읽기 6502 (BASE_STACK + ((sp + 1) & 0xFF)) | ((uint16_t) read6502 (BASE_STACK + ((sp + 2) & 0xFF)) << 8);
sp + = 2;
귀국 (temp16);
}
uint8_t pull8 () {
리턴 (read6502 (BASE_STACK + ++ sp));
}
void 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 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) 읽기 6502 (pc ++);
if (reladdr & 0x80) reladdr | = 0xFF00;
}
static void abso () {// 절대
ea = (uint16_t) read6502 (pc) | ((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)) {// 일부 opcode에서 페이지 교차를위한 한 번의주기 penlty
페널티 애드 터 = 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)) {// 일부 opcode에서 페이지 교차를위한 한 번의주기 penlty
페널티 애드 터 = 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) | ((도움 + 1) & 0x00FF); // 6502 페이지 경계 랩 어라운드 버그를 복제
ea = (uint16_t) read6502 (eahelp) | ((uint16_t) read6502 (eahelp2) << 8);
pc + = 2;
}
static void indx () {// (간접, X)
uint16_t 도움;
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) 읽기 6502 (pc ++);
eahelp2 = (eahelp & 0xFF00) | ((도움 + 1) & 0x00FF); // 제로 페이지 랩 어라운드
ea = (uint16_t) read6502 (eahelp) | ((uint16_t) read6502 (eahelp2) << 8);
시작 페이지 = ea & 0xFF00;
ea + = (uint16_t) y;
if (startpage! = (ea & 0xFF00)) {// 일부 opcode에서 페이지 교차를위한 한 번의주기 penlty
페널티 애드 터 = 1;
}
}
정적 uint16_t getvalue () {
if (addrtable [opcode] == acc) return ((uint16_t) a);
그렇지 않으면 return ((uint16_t) read6502 (ea));
}
정적 void putvalue (uint16_t saveval) {
만약 (addrtable [opcode] == acc) a = (uint8_t) (saveval & 0x00FF);
그렇지 않으면 write6502 (ea, (saveval & 0x00FF));
}
// 명령 핸들러 함수
정적 무효 adc () {
패널티 = 1;
값 = getvalue ();
결과 = (uint16_t) a + 값 + (uint16_t) (상태 및 FLAG_CARRY);
캐리 칼크 (결과);
제로 칼크 (결과);
overflowcalc (결과, a, 값);
signcalc (결과);
#ifndef NES_CPU
if (상태 및 FLAG_DECIMAL) {
clearcarry ();
if ((a & 0x0F)> 0x09) {
+ = 0x06;
}
if ((a & 0xF0)> 0x90) {
+ = 0x60;
setcarry ();
}
클락 틱스 6502 ++;
}
#endif
saveaccum (결과);
}
정적 무효 and () {
패널티 = 1;
값 = getvalue ();
결과 = (uint16_t) a & 값;
제로 칼크 (결과);
signcalc (결과);
saveaccum (결과);
}
정적 무효 asl () {
값 = getvalue ();
결과 = 값 << 1;
캐리 칼크 (결과);
제로 칼크 (결과);
signcalc (결과);
풋 가치 (결과);
}
정적 무효 bcc () {
if ((상태 및 FLAG_CARRY) == 0) {
oldpc = pc;
pc + = 렐라 드르;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // 점프가 페이지 경계를 넘 었는지 확인
그렇지 않으면 clockticks6502 ++;
}
}
정적 무효 bcs () {
if ((상태 및 FLAG_CARRY) == FLAG_CARRY) {
oldpc = pc;
pc + = 렐라 드르;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // 점프가 페이지 경계를 넘 었는지 확인
그렇지 않으면 clockticks6502 ++;
}
}
정적 무효 beq () {
if ((status & FLAG_ZERO) == FLAG_ZERO) {
oldpc = pc;
pc + = 렐라 드르;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // 점프가 페이지 경계를 넘 었는지 확인
그렇지 않으면 clockticks6502 ++;
}
}
정적 무효 비트 () {
값 = getvalue ();
결과 = (uint16_t) a & 값;
제로 칼크 (결과);
상태 = (상태 및 0x3F) | (uint8_t) (값 및 0xC0);
}
정적 무효 bmi () {
if ((status & FLAG_SIGN) == FLAG_SIGN) {
oldpc = pc;
pc + = 렐라 드르;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // 점프가 페이지 경계를 넘 었는지 확인
그렇지 않으면 clockticks6502 ++;
}
}
정적 무효 bne () {
if ((상태 및 FLAG_ZERO) == 0) {
oldpc = pc;
pc + = 렐라 드르;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // 점프가 페이지 경계를 넘 었는지 확인
그렇지 않으면 clockticks6502 ++;
}
}
정적 무효 bpl () {
if ((상태 및 FLAG_SIGN) == 0) {
oldpc = pc;
pc + = 렐라 드르;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // 점프가 페이지 경계를 넘 었는지 확인
그렇지 않으면 clockticks6502 ++;
}
}
정적 무효 brk () {
pc ++;
push16 (pc); // 다음 명령어 주소를 스택에 푸시
push8 (상태 | FLAG_BREAK); // 스택 상태로 CPU 상태를 푸시
setinterrupt (); // 인터럽트 플래그 설정
pc = (uint16_t) read6502 (0xFFFE) | ((uint16_t) read6502 (0xFFFF) << 8);
}
정적 무효 bvc () {
if ((상태 및 FLAG_OVERFLOW) == 0) {
oldpc = pc;
pc + = 렐라 드르;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // 점프가 페이지 경계를 넘 었는지 확인
그렇지 않으면 clockticks6502 ++;
}
}
정적 무효 bvs () {
if ((status & FLAG_OVERFLOW) == FLAG_OVERFLOW) {
oldpc = pc;
pc + = 렐라 드르;
if ((oldpc & 0xFF00)! = (pc & 0xFF00)) clockticks6502 + = 2; // 점프가 페이지 경계를 넘 었는지 확인
그렇지 않으면 clockticks6502 ++;
}
}
정적 무효 clc () {
clearcarry ();
}
정적 무효 cld () {
cleardecimal ();
}
정적 무효 cli () {
clearinterrupt ();
}
정적 무효 clv () {
clearoverflow ();
}
정적 무효 cmp () {
패널티 = 1;
값 = getvalue ();
결과 = (uint16_t) a-값;
(a> = (uint8_t) (값 & 0x00FF)) ifcarry () 인 경우;
그렇지 않으면 clearcarry ();
if (a == (uint8_t) (value & 0x00FF)) setzero ();
그렇지 않으면 clearzero ();
signcalc (결과);
}
정적 무효 cpx () {
값 = getvalue ();
결과 = (uint16_t) x-값;
만약 (x> = (uint8_t) (value & 0x00FF))이면 setcarry ();
그렇지 않으면 clearcarry ();
if (x == (uint8_t) (value & 0x00FF)) setzero ();
그렇지 않으면 clearzero ();
signcalc (결과);
}
정적 무효 cpy () {
값 = getvalue ();
결과 = (uint16_t) y-값;
(y> = (uint8_t) (값 & 0x00FF))이면 setcarry ();
그렇지 않으면 clearcarry ();
if (y == (uint8_t) (값 & 0x00FF)) setzero ();
그렇지 않으면 clearzero ();
signcalc (결과);
}
정적 무효 dec () {
값 = getvalue ();
결과 = 값-1;
제로 칼크 (결과);
signcalc (결과);
풋 가치 (결과);
}
정적 무효 dex () {
엑스--;
제로 칼크 (x);
signcalc (x);
}
정적 무효 dey () {
와이--;
제로 칼크 (y);
signcalc (y);
}
정적 무효 eor () {
패널티 = 1;
값 = getvalue ();
결과 = (uint16_t) a ^ 값;
제로 칼크 (결과);
signcalc (결과);
saveaccum (결과);
}
정적 무효 inc () {
값 = getvalue ();
결과 = 값 + 1;
제로 칼크 (결과);
signcalc (결과);
풋 가치 (결과);
}
정적 무효 inx () {
x ++;
제로 칼크 (x);
signcalc (x);
}
정적 무효 iny () {
y ++;
제로 칼크 (y);
signcalc (y);
}
정적 무효 jmp () {
pc = ea;
}
정적 무효 jsr () {
push16 (pc-1);
pc = ea;
}
정적 무효 lda () {
패널티 = 1;
값 = getvalue ();
a = (uint8_t) (값 및 0x00FF);
제로 칼크 (a);
signcalc (a);
}
정적 무효 ldx () {
패널티 = 1;
값 = getvalue ();
x = (uint8_t) (값 및 0x00FF);
제로 칼크 (x);
signcalc (x);
}
정적 무효 ldy () {
패널티 = 1;
값 = getvalue ();
y = (uint8_t) (값 및 0x00FF);
제로 칼크 (y);
signcalc (y);
}
정적 무효 lsr () {
값 = getvalue ();
결과 = 값 >> 1;
if (value & 1) setcarry ();
그렇지 않으면 clearcarry ();
제로 칼크 (결과);
signcalc (결과);
풋 가치 (결과);
}
정적 무효 nop () {
스위치 (opcode) {
사례 0x1C :
사례 0x3C :
사례 0x5C :
사례 0x7C :
사례 0xDC :
사례 0xFC :
패널티 = 1;
단절;
}
}
정적 무효 ora () {
패널티 = 1;
값 = getvalue ();
결과 = (uint16_t) a | 값;
제로 칼크 (결과);
signcalc (결과);
saveaccum (결과);
}
정적 무효 pha () {
푸시 8 (a);
}
정적 무효 php () {
push8 (상태 | FLAG_BREAK);
}
정적 무효 pla () {
a = pull8 ();
제로 칼크 (a);
signcalc (a);
}
정적 무효 plp () {
상태 = pull8 () | FLAG_CONSTANT;
}
정적 무효 rol () {
값 = getvalue ();
결과 = (값 << 1) | (상태 및 FLAG_CARRY);
캐리 칼크 (결과);
제로 칼크 (결과);
signcalc (결과);
풋 가치 (결과);
}
정적 무효 ror () {
값 = getvalue ();
결과 = (값 >> 1) | ((상태 및 FLAG_CARRY) << 7);
if (value & 1) setcarry ();
그렇지 않으면 clearcarry ();
제로 칼크 (결과);
signcalc (결과);
풋 가치 (결과);
}
정적 무효 rti () {
상태 = pull8 ();
값 = pull16 ();
pc = 값;
}
정적 무효 rts () {
값 = pull16 ();
pc = 값 + 1;
}
정적 무효 sbc () {
패널티 = 1;
값 = getvalue () ^ 0x00FF;
결과 = (uint16_t) a + 값 + (uint16_t) (상태 및 FLAG_CARRY);
캐리 칼크 (결과);
제로 칼크 (결과);
overflowcalc (결과, a, 값);
signcalc (결과);
#ifndef NES_CPU
if (상태 및 FLAG_DECIMAL) {
clearcarry ();
-= 0x66;
if ((a & 0x0F)> 0x09) {
+ = 0x06;
}
if ((a & 0xF0)> 0x90) {
+ = 0x60;
setcarry ();
}
클락 틱스 6502 ++;
}
#endif
saveaccum (결과);
}
정적 무효 sec () {
setcarry ();
}
정적 무효 sed () {
setdecimal ();
}
정적 무효 sei () {
setinterrupt ();
}
정적 무효 sta () {
풋 가치 (a);
}
정적 무효 stx () {
putvalue (x);
}
정적 void sty () {
풋 가치 (y);
}
정적 무효 세금 () {
x = a;
제로 칼크 (x);
signcalc (x);
}
정적 무효 tay () {
y = a;
제로 칼크 (y);
signcalc (y);
}
정적 무효 tsx () {
x = sp;
제로 칼크 (x);
signcalc (x);
}
정적 void txa () {
a = x;
제로 칼크 (a);
signcalc (a);
}
정적 무효 txs () {
sp = x;
}
정적 무효 tya () {
a = y;
제로 칼크 (a);
signcalc (a);
}
// 언급되지 않은 지침
#ifdef 문서화되지 않은
정적 무효 lax () {
lda ();
ldx ();
}
정적 무효 색소폰 () {
sta ();
stx ();
putvalue (a & x);
if (penaltyop && 패널티 주소) clockticks6502--;
}
정적 무효 dcp () {
dec ();
cmp ();
if (penaltyop && 패널티 주소) clockticks6502--;
}
정적 무효 isb () {
inc ();
sbc ();
if (penaltyop && 패널티 주소) clockticks6502--;
}
정적 무효 slo () {
asl ();
오라 ();
if (penaltyop && 패널티 주소) clockticks6502--;
}
정적 무효 rla () {
rol ();
과();
if (penaltyop && 패널티 주소) clockticks6502--;
}
정적 무효 sre () {
lsr ();
eor ();
if (penaltyop && 패널티 주소) clockticks6502--;
}
정적 무효 rra () {
ror ();
adc ();
if (penaltyop && 패널티 주소) clockticks6502--;
}
#그밖에
# 정의 lax nop
# 색소폰 nop 정의
# dcp nop 정의
# isb nop 정의
#slo nop 정의
#rla nop 정의
#sre nop 정의
# 라피 노프 정의
#endif
정적 무효 (* addrtable [256]) () = {
/ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | 전자 | 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 * /
};
정적 void (* optable [256]) () = {
/ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | 전자 | 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 및 and, rol, nop, 비트 및 rol, rla, / * 2 * /
/ * 3 * / bmi 및 nop, rla, nop 및 and rol, rla, sec 및 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 * / 숨은 참조, 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, 세금, 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 * /
};
정적 const uint32_t ticktable [256] = {
/ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | 전자 | 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 () {
push16 (pc);
push8 (상태);
상태 | = FLAG_INTERRUPT;
pc = (uint16_t) read6502 (0xFFFA) | ((uint16_t) read6502 (0xFFFB) << 8);
}
무효 irq6502 () {
push16 (pc);
push8 (상태);
상태 | = FLAG_INTERRUPT;
pc = (uint16_t) read6502 (0xFFFE) | ((uint16_t) read6502 (0xFFFF) << 8);
}
uint8_t callexternal = 0;
무효 (* loopexternal) ();
무효 exec6502 (uint32_t 틱 카운트) {
clockgoal6502 + = 틱 카운트;
while (clockticks6502 <clockgoal6502) {
opcode = read6502 (pc ++);
패널티 = 0;
페널티 애더 = 0;
(* addrtable [opcode]) ();
(* optable [opcode]) ();
clockticks6502 + = 틱 테이블 [opcode];
if (penaltyop && 패널티 주소) clockticks6502 ++;
지침 ++;
if (callexternal) (* loopexternal) ();
}
}
void step6502 () {
opcode = read6502 (pc ++);
패널티 = 0;
페널티 애드 = 0;
(* addrtable [opcode]) ();
(* optable [opcode]) ();
clockticks6502 + = 틱 테이블 [opcode];
if (penaltyop && 패널티 주소) clockticks6502 ++;
clockgoal6502 = 클락 틱스 6502;
지침 ++;
if (callexternal) (* loopexternal) ();
}
void hookexternal (void * funcptr) {
if (funcptr! = (void *) NULL) {
loopexternal = funcptr;
callexternal = 1;
} 그렇지 않으면 callexternal = 0;
}