Merge pull request #1 from robmcmullen/legal_instructions
Decimal mode & passes torture tests
This commit is contained in:
commit
7e3ef5bd78
138
6502-emu.c
138
6502-emu.c
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
|
||||
|
@ -18,18 +19,28 @@ void step_delay()
|
|||
nanosleep(&req, &rem);
|
||||
}
|
||||
|
||||
void run_cpu()
|
||||
void run_cpu(long cycle_stop, int verbose, int mem_dump, int break_pc, int fast)
|
||||
{
|
||||
int cycles = 0;
|
||||
long cycles = 0;
|
||||
int cycles_per_step = (CPU_FREQ / (ONE_SECOND / STEP_DURATION));
|
||||
|
||||
for (;;) {
|
||||
for (cycles %= cycles_per_step; cycles < cycles_per_step;) {
|
||||
cycles += step_cpu();
|
||||
if (mem_dump) save_memory(NULL);
|
||||
cycles += step_cpu(verbose);
|
||||
if ((cycle_stop > 0) && (total_cycles >= cycle_stop)) goto end;
|
||||
step_uart();
|
||||
|
||||
if (break_pc >= 0 && PC == (uint16_t)break_pc) {
|
||||
fprintf(stderr, "break at %04x\n", break_pc);
|
||||
save_memory(NULL);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
step_delay(); // remove this for more speed
|
||||
if (!fast) step_delay();
|
||||
}
|
||||
end:
|
||||
return;
|
||||
}
|
||||
|
||||
void restore_stdin()
|
||||
|
@ -48,26 +59,123 @@ void raw_stdin()
|
|||
atexit(restore_stdin);
|
||||
}
|
||||
|
||||
int hextoint(char *str) {
|
||||
int val;
|
||||
|
||||
if (*str == '$') str++;
|
||||
val = strtol(str, NULL, 16);
|
||||
return val;
|
||||
}
|
||||
|
||||
void usage(char *argv[]) {
|
||||
fprintf(stderr, "Usage: %s [OPTIONS] FILE\n"
|
||||
"Simulate a NMOS 6502 processor\n"
|
||||
"\nOPTIONS:\n"
|
||||
"\n CPU Initialization (specify all values in hex; $nn, 0xNN, etc.)\n"
|
||||
" -a HEX set A register (default 0)\n"
|
||||
" -x HEX set X register (default 0)\n"
|
||||
" -y HEX set Y register (default 0)\n"
|
||||
" -s HEX set stack pointer (default $ff)\n"
|
||||
" -p HEX set processor status register (default 0)\n"
|
||||
" -r ADDR set initial run address (default: use value at RST_VEC)\n"
|
||||
"\n Emulator Control\n"
|
||||
" -v print CPU info at every step\n"
|
||||
" -i connect stdin/stdout to the emulator\n"
|
||||
" -b ADDR stop when PC reaches this address, write memory dump, and exit\n"
|
||||
" -c NUM exit after number of cycles (default: never)\n"
|
||||
" -f run as fast as possible; no delay loop\n"
|
||||
"\n Memory Initialization\n"
|
||||
" -l ADDR load address for ROM file (default $c000)\n"
|
||||
" FILE binary file to load\n"
|
||||
, argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s file.rom\n", argv[0]);
|
||||
printf("The first 16k of \"file.rom\" is loaded into the last 16k of memory.\n");
|
||||
int a, x, y, sp, sr, pc, load_addr;
|
||||
int verbose, interactive, mem_dump, break_pc, fast;
|
||||
long cycles;
|
||||
int opt;
|
||||
|
||||
verbose = 0;
|
||||
interactive = 0;
|
||||
mem_dump = 0;
|
||||
cycles = 0;
|
||||
load_addr = 0xC000;
|
||||
break_pc = -1;
|
||||
fast = 0;
|
||||
a = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
sp = 0xFF;
|
||||
sr = 0;
|
||||
pc = -RST_VEC; // negative implies indirect
|
||||
while ((opt = getopt(argc, argv, "hvimfa:b:x:y:r:p:s:g:c:l:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'i':
|
||||
interactive = 1;
|
||||
break;
|
||||
case 'm':
|
||||
mem_dump = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fast = 1;
|
||||
break;
|
||||
case 'b':
|
||||
break_pc = hextoint(optarg);
|
||||
break;
|
||||
case 'a':
|
||||
a = hextoint(optarg);
|
||||
break;
|
||||
case 'x':
|
||||
x = hextoint(optarg);
|
||||
break;
|
||||
case 'y':
|
||||
y = hextoint(optarg);
|
||||
break;
|
||||
case 's':
|
||||
sp = hextoint(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
sr = hextoint(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
case 'g':
|
||||
pc = hextoint(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
cycles = atol(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
load_addr = hextoint(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
default: /* '?' */
|
||||
usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "Error: expected binary file to load\n\n");
|
||||
usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (load_rom(argv[optind], load_addr) != 0) {
|
||||
printf("Error loading \"%s\".\n", argv[optind]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (load_rom(argv[1]) != 0) {
|
||||
printf("Error loading \"%s\".\n", argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
raw_stdin(); // allow individual keystrokes to be detected
|
||||
if (interactive) raw_stdin(); // allow individual keystrokes to be detected
|
||||
|
||||
init_tables();
|
||||
init_uart();
|
||||
|
||||
reset_cpu();
|
||||
run_cpu();
|
||||
reset_cpu(a, x, y, sp, sr, pc);
|
||||
run_cpu(cycles, verbose, mem_dump, break_pc, fast);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
723
6502.c
723
6502.c
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include "6502.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
int lengths[NUM_MODES]; // instruction length table, indexed by addressing mode
|
||||
uint8_t * (*get_ptr[NUM_MODES])(); // addressing mode decoder table
|
||||
Instruction instructions[0x100]; // instruction data table
|
||||
|
@ -48,12 +46,29 @@ static inline uint8_t * write_ptr()
|
|||
return write_addr = get_ptr[inst.mode]();
|
||||
}
|
||||
|
||||
/* Branch logic common to all branch instructions */
|
||||
|
||||
static inline void take_branch()
|
||||
{
|
||||
uint16_t oldPC;
|
||||
oldPC = PC + 2; // PC has already moved to point to the next instruction
|
||||
PC = read_ptr() - memory;
|
||||
if ((PC ^ oldPC) & 0xff00) extra_cycles += 1; // addr crosses page boundary
|
||||
extra_cycles += 1;
|
||||
}
|
||||
|
||||
/* Instruction Implementations */
|
||||
|
||||
static void inst_ADC()
|
||||
{
|
||||
uint8_t operand = * read_ptr();
|
||||
int tmp = A + operand + (SR.bits.carry & 1);
|
||||
unsigned int tmp = A + operand + (SR.bits.carry & 1);
|
||||
if (SR.bits.decimal) {
|
||||
tmp = (A & 0x0f) + (operand & 0x0f) + (SR.bits.carry & 1);
|
||||
if (tmp >= 10) tmp = (tmp - 10) | 0x10;
|
||||
tmp += (A & 0xf0) + (operand & 0xf0);
|
||||
if (tmp > 0x9f) tmp += 0x60;
|
||||
}
|
||||
SR.bits.carry = tmp > 0xFF;
|
||||
SR.bits.overflow = ((A^tmp)&(operand^tmp)&0x80) != 0;
|
||||
A = tmp & 0xFF;
|
||||
|
@ -81,21 +96,21 @@ static void inst_ASL()
|
|||
static void inst_BCC()
|
||||
{
|
||||
if (!SR.bits.carry) {
|
||||
PC = read_ptr() - memory;
|
||||
take_branch();
|
||||
}
|
||||
}
|
||||
|
||||
static void inst_BCS()
|
||||
{
|
||||
if (SR.bits.carry) {
|
||||
PC = read_ptr() - memory;
|
||||
take_branch();
|
||||
}
|
||||
}
|
||||
|
||||
static void inst_BEQ()
|
||||
{
|
||||
if (SR.bits.zero) {
|
||||
PC = read_ptr() - memory;
|
||||
take_branch();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,21 +125,21 @@ static void inst_BIT()
|
|||
static void inst_BMI()
|
||||
{
|
||||
if (SR.bits.sign) {
|
||||
PC = read_ptr() - memory;
|
||||
take_branch();
|
||||
}
|
||||
}
|
||||
|
||||
static void inst_BNE()
|
||||
{
|
||||
if (!SR.bits.zero) {
|
||||
PC = read_ptr() - memory;
|
||||
take_branch();
|
||||
}
|
||||
}
|
||||
|
||||
static void inst_BPL()
|
||||
{
|
||||
if (!SR.bits.sign) {
|
||||
PC = read_ptr() - memory;
|
||||
take_branch();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,14 +160,14 @@ static void inst_BRK()
|
|||
static void inst_BVC()
|
||||
{
|
||||
if (!SR.bits.overflow) {
|
||||
PC = read_ptr() - memory;
|
||||
take_branch();
|
||||
}
|
||||
}
|
||||
|
||||
static void inst_BVS()
|
||||
{
|
||||
if (SR.bits.overflow) {
|
||||
PC = read_ptr() - memory;
|
||||
take_branch();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -305,7 +320,9 @@ static void inst_LSR()
|
|||
|
||||
static void inst_NOP()
|
||||
{
|
||||
// nothing
|
||||
// thrown away, just used to compute any extra cycles for the multi-byte
|
||||
// NOP statements
|
||||
read_ptr();
|
||||
}
|
||||
|
||||
static void inst_ORA()
|
||||
|
@ -322,8 +339,16 @@ static void inst_PHA()
|
|||
|
||||
static void inst_PHP()
|
||||
{
|
||||
SR.bits.brk = 1; // this is slightly unexpected, but it's what the real hardware does.
|
||||
stack_push(SR.byte);
|
||||
union StatusReg pushed_sr;
|
||||
|
||||
// PHP sets the BRK flag in the byte that is pushed onto the stack,
|
||||
// but doesn't affect the status register itself. this is slightly
|
||||
// unexpected, but it's what the real hardware does.
|
||||
//
|
||||
// See http://visual6502.org/wiki/index.php?title=6502_BRK_and_B_bit
|
||||
pushed_sr.byte = SR.byte;
|
||||
pushed_sr.bits.brk = 1;
|
||||
stack_push(pushed_sr.byte);
|
||||
}
|
||||
|
||||
static void inst_PLA()
|
||||
|
@ -337,6 +362,7 @@ static void inst_PLP()
|
|||
{
|
||||
SR.byte = stack_pull();
|
||||
SR.bits.unused = 1;
|
||||
SR.bits.brk = 0;
|
||||
}
|
||||
|
||||
static void inst_ROL()
|
||||
|
@ -381,11 +407,21 @@ static void inst_RTS()
|
|||
|
||||
static void inst_SBC()
|
||||
{
|
||||
uint8_t operand = ~(* read_ptr()); // identical to ACD with the operand inverted
|
||||
int tmp = A + operand + (SR.bits.carry & 1);
|
||||
SR.bits.carry = tmp > 0xFF;
|
||||
SR.bits.overflow = ((A^tmp)&(operand^tmp)&0x80) != 0;
|
||||
A = tmp & 0xFF;
|
||||
uint8_t operand = * read_ptr();
|
||||
unsigned int tmp, lo, hi;
|
||||
tmp = A - operand - 1 + (SR.bits.carry & 1);
|
||||
SR.bits.overflow = ((A^tmp)&(A^operand)&0x80) != 0;
|
||||
if (SR.bits.decimal) {
|
||||
lo = (A & 0x0f) - (operand & 0x0f) - 1 + SR.bits.carry;
|
||||
hi = (A >> 4) - (operand >> 4);
|
||||
if (lo & 0x10) lo -= 6, hi--;
|
||||
if (hi & 0x10) hi -= 6;
|
||||
A = (hi << 4) | (lo & 0x0f);
|
||||
}
|
||||
else {
|
||||
A = tmp & 0xFF;
|
||||
}
|
||||
SR.bits.carry = tmp < 0x100;
|
||||
N_flag(A);
|
||||
Z_flag(A);
|
||||
}
|
||||
|
@ -398,7 +434,6 @@ static void inst_SEC()
|
|||
static void inst_SED()
|
||||
{
|
||||
SR.bits.decimal = 1;
|
||||
printf("DECIMAL! :(\r\n"); // TODO
|
||||
}
|
||||
|
||||
static void inst_SEI()
|
||||
|
@ -409,6 +444,7 @@ static void inst_SEI()
|
|||
static void inst_STA()
|
||||
{
|
||||
* write_ptr() = A;
|
||||
extra_cycles = 0; // STA has no addressing modes that use the extra cycle
|
||||
}
|
||||
|
||||
static void inst_STX()
|
||||
|
@ -463,6 +499,13 @@ static void inst_TYA()
|
|||
|
||||
/* Addressing Implementations */
|
||||
|
||||
uint8_t * get_IMPL()
|
||||
{
|
||||
// dummy implementation; for completeness necessary for cycle counting NOP
|
||||
// instructions
|
||||
return &memory[0];
|
||||
}
|
||||
|
||||
uint8_t * get_IMM()
|
||||
{
|
||||
return &memory[(uint16_t) (PC+1)];
|
||||
|
@ -502,12 +545,18 @@ uint8_t * get_ABS()
|
|||
|
||||
uint8_t * get_ABSX()
|
||||
{
|
||||
return &memory[(uint16_t) (get_uint16() + X)];
|
||||
uint16_t ptr;
|
||||
ptr = (uint16_t)(get_uint16() + X);
|
||||
if ((uint8_t)ptr < X) extra_cycles ++;
|
||||
return &memory[ptr];
|
||||
}
|
||||
|
||||
uint8_t * get_ABSY()
|
||||
{
|
||||
return &memory[(uint16_t) (get_uint16() + Y)];
|
||||
uint16_t ptr;
|
||||
ptr = (uint16_t)(get_uint16() + Y);
|
||||
if ((uint8_t)ptr < Y) extra_cycles ++;
|
||||
return &memory[ptr];
|
||||
}
|
||||
|
||||
uint8_t * get_IND()
|
||||
|
@ -520,15 +569,28 @@ uint8_t * get_IND()
|
|||
uint8_t * get_XIND()
|
||||
{
|
||||
uint16_t ptr;
|
||||
memcpy(&ptr, get_ZPX(), sizeof(ptr));
|
||||
ptr = ((* get_IMM()) + X) & 0xFF;
|
||||
if (ptr == 0xff) { // check for wraparound in zero page
|
||||
ptr = memory[ptr] + (memory[ptr & 0xff00] << 8);
|
||||
}
|
||||
else {
|
||||
memcpy(&ptr, &memory[ptr], sizeof(ptr));
|
||||
}
|
||||
return &memory[ptr];
|
||||
}
|
||||
|
||||
uint8_t * get_INDY()
|
||||
{
|
||||
uint16_t ptr;
|
||||
memcpy(&ptr, get_ZP(), sizeof(ptr));
|
||||
ptr = * get_IMM();
|
||||
if (ptr == 0xff) { // check for wraparound in zero page
|
||||
ptr = memory[ptr] + (memory[ptr & 0xff00] << 8);
|
||||
}
|
||||
else {
|
||||
memcpy(&ptr, &memory[ptr], sizeof(ptr));
|
||||
}
|
||||
ptr += Y;
|
||||
if ((uint8_t)ptr < Y) extra_cycles ++;
|
||||
return &memory[ptr];
|
||||
}
|
||||
|
||||
|
@ -537,6 +599,28 @@ uint8_t * get_REL()
|
|||
return &memory[(uint16_t) (PC + (int8_t) * get_IMM())];
|
||||
}
|
||||
|
||||
uint8_t * get_JMP_IND_BUG()
|
||||
{
|
||||
uint8_t * addr;
|
||||
uint16_t ptr;
|
||||
|
||||
ptr = get_uint16();
|
||||
if ((ptr & 0xff) == 0xff) {
|
||||
// Bug when crosses a page boundary. When using relative index ($xxff),
|
||||
// instead of using the last byte of the page and the first byte of the
|
||||
// next page, it uses the first byte of the same page. E.g. jmp ($baff)
|
||||
// would use the value at $baff as the LSB, but $ba00 as the high byte
|
||||
// instead of $bb00. This was fixed in the 65C02
|
||||
ptr = memory[ptr] + (memory[ptr & 0xff00] << 8);
|
||||
|
||||
}
|
||||
else {
|
||||
addr = &memory[ptr];
|
||||
memcpy(&ptr, addr, sizeof(ptr));
|
||||
}
|
||||
return &memory[ptr];
|
||||
}
|
||||
|
||||
|
||||
/* Construction of Tables */
|
||||
|
||||
|
@ -557,7 +641,8 @@ void init_tables() // this is only done at runtime to improve code readability.
|
|||
lengths[ZP] = 2;
|
||||
lengths[ZPX] = 2;
|
||||
lengths[ZPY] = 2;
|
||||
|
||||
lengths[JMP_IND_BUG] = 3;
|
||||
|
||||
/* Addressing Modes */
|
||||
|
||||
get_ptr[ACC] = get_ACC;
|
||||
|
@ -565,6 +650,7 @@ void init_tables() // this is only done at runtime to improve code readability.
|
|||
get_ptr[ABSX] = get_ABSX;
|
||||
get_ptr[ABSY] = get_ABSY;
|
||||
get_ptr[IMM] = get_IMM;
|
||||
get_ptr[IMPL] = get_IMPL;
|
||||
get_ptr[IND] = get_IND;
|
||||
get_ptr[XIND] = get_XIND;
|
||||
get_ptr[INDY] = get_INDY;
|
||||
|
@ -572,283 +658,291 @@ void init_tables() // this is only done at runtime to improve code readability.
|
|||
get_ptr[ZP] = get_ZP;
|
||||
get_ptr[ZPX] = get_ZPX;
|
||||
get_ptr[ZPY] = get_ZPY;
|
||||
|
||||
get_ptr[JMP_IND_BUG] = get_JMP_IND_BUG;
|
||||
|
||||
/* Instructions */
|
||||
|
||||
instructions[0x00] = (Instruction) {"BRK impl", inst_BRK, IMPL, 7,};
|
||||
instructions[0x00] = (Instruction) {"BRK impl", inst_BRK, IMPL, 7};
|
||||
instructions[0x01] = (Instruction) {"ORA X,ind", inst_ORA, XIND, 6};
|
||||
instructions[0x02] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x03] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x04] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x05] = (Instruction) {"ORA zpg", inst_ORA, ZP, 5};
|
||||
instructions[0x06] = (Instruction) {"ASL zpg", inst_ASL, ZP, 1};
|
||||
instructions[0x07] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x08] = (Instruction) {"PHP impl", inst_PHP, IMPL, 1};
|
||||
instructions[0x09] = (Instruction) {"ORA #", inst_ORA, IMM, 1};
|
||||
instructions[0x0A] = (Instruction) {"ASL A", inst_ASL, ACC, 1};
|
||||
instructions[0x0B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x0C] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x0D] = (Instruction) {"ORA abs", inst_ORA, ABS, 1};
|
||||
instructions[0x0E] = (Instruction) {"ASL abs", inst_ASL, ABS, 1};
|
||||
instructions[0x0F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x10] = (Instruction) {"BPL rel", inst_BPL, REL, 1};
|
||||
instructions[0x11] = (Instruction) {"ORA ind,Y", inst_ORA, INDY, 1};
|
||||
instructions[0x12] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x13] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x14] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x15] = (Instruction) {"ORA zpg,X", inst_ORA, ZPX, 1};
|
||||
instructions[0x16] = (Instruction) {"ASL zpg,X", inst_ASL, ZPX, 1};
|
||||
instructions[0x17] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x18] = (Instruction) {"CLC impl", inst_CLC, IMPL, 1};
|
||||
instructions[0x19] = (Instruction) {"ORA abs,Y", inst_ORA, ABSY, 1};
|
||||
instructions[0x1A] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x1B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x1C] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x1D] = (Instruction) {"ORA abs,X", inst_ORA, ABSX, 1};
|
||||
instructions[0x1E] = (Instruction) {"ASL abs,X", inst_ASL, ABSX, 1};
|
||||
instructions[0x1F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x20] = (Instruction) {"JSR abs", inst_JSR, ABS, 1};
|
||||
instructions[0x21] = (Instruction) {"AND X,ind", inst_AND, XIND, 1};
|
||||
instructions[0x22] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x23] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x24] = (Instruction) {"BIT zpg", inst_BIT, ZP, 1};
|
||||
instructions[0x25] = (Instruction) {"AND zpg", inst_AND, ZP, 1};
|
||||
instructions[0x26] = (Instruction) {"ROL zpg", inst_ROL, ZP, 1};
|
||||
instructions[0x27] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x28] = (Instruction) {"PLP impl", inst_PLP, IMPL, 1};
|
||||
instructions[0x29] = (Instruction) {"AND #", inst_AND, IMM, 1};
|
||||
instructions[0x2A] = (Instruction) {"ROL A", inst_ROL, ACC, 1};
|
||||
instructions[0x2B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x2C] = (Instruction) {"BIT abs", inst_BIT, ABS, 1};
|
||||
instructions[0x2D] = (Instruction) {"AND abs", inst_AND, ABS, 1};
|
||||
instructions[0x2E] = (Instruction) {"ROL abs", inst_ROL, ABS, 1};
|
||||
instructions[0x2F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x30] = (Instruction) {"BMI rel", inst_BMI, REL, 1};
|
||||
instructions[0x31] = (Instruction) {"AND ind,Y", inst_AND, INDY, 1};
|
||||
instructions[0x32] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x33] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x34] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x35] = (Instruction) {"AND zpg,X", inst_AND, ZPX, 1};
|
||||
instructions[0x36] = (Instruction) {"ROL zpg,X", inst_ROL, ZPX, 1};
|
||||
instructions[0x37] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x38] = (Instruction) {"SEC impl", inst_SEC, IMPL, 1};
|
||||
instructions[0x39] = (Instruction) {"AND abs,Y", inst_AND, ABSY, 1};
|
||||
instructions[0x3A] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x3B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x3C] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x3D] = (Instruction) {"AND abs,X", inst_AND, ABSX, 1};
|
||||
instructions[0x3E] = (Instruction) {"ROL abs,X", inst_ROL, ABSX, 1};
|
||||
instructions[0x3F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x40] = (Instruction) {"RTI impl", inst_RTI, IMPL, 1};
|
||||
instructions[0x41] = (Instruction) {"EOR X,ind", inst_EOR, XIND, 1};
|
||||
instructions[0x42] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x43] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x44] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x45] = (Instruction) {"EOR zpg", inst_EOR, ZP, 1};
|
||||
instructions[0x46] = (Instruction) {"LSR zpg", inst_LSR, ZP, 1};
|
||||
instructions[0x47] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x48] = (Instruction) {"PHA impl", inst_PHA, IMPL, 1};
|
||||
instructions[0x49] = (Instruction) {"EOR #", inst_EOR, IMM, 1};
|
||||
instructions[0x4A] = (Instruction) {"LSR A", inst_LSR, ACC, 1};
|
||||
instructions[0x4B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x4C] = (Instruction) {"JMP abs", inst_JMP, ABS, 1};
|
||||
instructions[0x4D] = (Instruction) {"EOR abs", inst_EOR, ABS, 1};
|
||||
instructions[0x4E] = (Instruction) {"LSR abs", inst_LSR, ABS, 1};
|
||||
instructions[0x4F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x50] = (Instruction) {"BVC rel", inst_BVC, REL, 1};
|
||||
instructions[0x51] = (Instruction) {"EOR ind,Y", inst_EOR, INDY, 1};
|
||||
instructions[0x52] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x53] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x54] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x55] = (Instruction) {"EOR zpg,X", inst_EOR, ZPX, 1};
|
||||
instructions[0x56] = (Instruction) {"LSR zpg,X", inst_LSR, ZPX, 1};
|
||||
instructions[0x57] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x58] = (Instruction) {"CLI impl", inst_CLI, IMPL, 1};
|
||||
instructions[0x59] = (Instruction) {"EOR abs,Y", inst_EOR, ABSY, 1};
|
||||
instructions[0x5A] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x5B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x5C] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x5D] = (Instruction) {"EOR abs,X", inst_EOR, ABSX, 1};
|
||||
instructions[0x5E] = (Instruction) {"LSR abs,X", inst_LSR, ABSX, 1};
|
||||
instructions[0x5F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x60] = (Instruction) {"RTS impl", inst_RTS, IMPL, 1};
|
||||
instructions[0x61] = (Instruction) {"ADC X,ind", inst_ADC, XIND, 1};
|
||||
instructions[0x62] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x63] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x64] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x65] = (Instruction) {"ADC zpg", inst_ADC, ZP, 1};
|
||||
instructions[0x66] = (Instruction) {"ROR zpg", inst_ROR, ZP, 1};
|
||||
instructions[0x67] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x68] = (Instruction) {"PLA impl", inst_PLA, IMPL, 1};
|
||||
instructions[0x69] = (Instruction) {"ADC #", inst_ADC, IMM, 1};
|
||||
instructions[0x6A] = (Instruction) {"ROR A", inst_ROR, ACC, 1};
|
||||
instructions[0x6B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x6C] = (Instruction) {"JMP ind", inst_JMP, IND, 1};
|
||||
instructions[0x6D] = (Instruction) {"ADC abs", inst_ADC, ABS, 1};
|
||||
instructions[0x6E] = (Instruction) {"ROR abs", inst_ROR, ABS, 1};
|
||||
instructions[0x6F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x70] = (Instruction) {"BVS rel", inst_BVS, REL, 1};
|
||||
instructions[0x71] = (Instruction) {"ADC ind,Y", inst_ADC, INDY, 1};
|
||||
instructions[0x72] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x73] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x74] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x75] = (Instruction) {"ADC zpg,X", inst_ADC, ZPX, 1};
|
||||
instructions[0x76] = (Instruction) {"ROR zpg,X", inst_ROR, ZPX, 1};
|
||||
instructions[0x77] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x78] = (Instruction) {"SEI impl", inst_SEI, IMPL, 1};
|
||||
instructions[0x79] = (Instruction) {"ADC abs,Y", inst_ADC, ABSY, 1};
|
||||
instructions[0x7A] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x7B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x7C] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x7D] = (Instruction) {"ADC abs,X", inst_ADC, ABSX, 1};
|
||||
instructions[0x7E] = (Instruction) {"ROR abs,X", inst_ROR, ABSX, 1};
|
||||
instructions[0x7F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x80] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x81] = (Instruction) {"STA X,ind", inst_STA, XIND, 1};
|
||||
instructions[0x82] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x83] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x84] = (Instruction) {"STY zpg", inst_STY, ZP, 1};
|
||||
instructions[0x85] = (Instruction) {"STA zpg", inst_STA, ZP, 1};
|
||||
instructions[0x86] = (Instruction) {"STX zpg", inst_STX, ZP, 1};
|
||||
instructions[0x87] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x88] = (Instruction) {"DEY impl", inst_DEY, IMPL, 1};
|
||||
instructions[0x89] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x8A] = (Instruction) {"TXA impl", inst_TXA, IMPL, 1};
|
||||
instructions[0x8B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x8C] = (Instruction) {"STY abs", inst_STY, ABS, 1};
|
||||
instructions[0x8D] = (Instruction) {"STA abs", inst_STA, ABS, 1};
|
||||
instructions[0x8E] = (Instruction) {"STX abs", inst_STX, ABS, 1};
|
||||
instructions[0x8F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x90] = (Instruction) {"BCC rel", inst_BCC, REL, 1};
|
||||
instructions[0x91] = (Instruction) {"STA ind,Y", inst_STA, INDY, 1};
|
||||
instructions[0x92] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x93] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x94] = (Instruction) {"STY zpg,X", inst_STY, ZPX, 1};
|
||||
instructions[0x95] = (Instruction) {"STA zpg,X", inst_STA, ZPX, 1};
|
||||
instructions[0x96] = (Instruction) {"STX zpg,Y", inst_STX, ZPY, 1};
|
||||
instructions[0x97] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x98] = (Instruction) {"TYA impl", inst_TYA, IMPL, 1};
|
||||
instructions[0x99] = (Instruction) {"STA abs,Y", inst_STA, ABSY, 1};
|
||||
instructions[0x9A] = (Instruction) {"TXS impl", inst_TXS, IMPL, 1};
|
||||
instructions[0x9B] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x9C] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x9D] = (Instruction) {"STA abs,X", inst_STA, ABSX, 1};
|
||||
instructions[0x9E] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x9F] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xA0] = (Instruction) {"LDY #", inst_LDY, IMM, 1};
|
||||
instructions[0xA1] = (Instruction) {"LDA X,ind", inst_LDA, XIND, 1};
|
||||
instructions[0xA2] = (Instruction) {"LDX #", inst_LDX, IMM, 1};
|
||||
instructions[0xA3] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xA4] = (Instruction) {"LDY zpg", inst_LDY, ZP, 1};
|
||||
instructions[0xA5] = (Instruction) {"LDA zpg", inst_LDA, ZP, 1};
|
||||
instructions[0xA6] = (Instruction) {"LDX zpg", inst_LDX, ZP, 1};
|
||||
instructions[0xA7] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xA8] = (Instruction) {"TAY impl", inst_TAY, IMPL, 1};
|
||||
instructions[0xA9] = (Instruction) {"LDA #", inst_LDA, IMM, 1};
|
||||
instructions[0xAA] = (Instruction) {"TAX impl", inst_TAX, IMPL, 1};
|
||||
instructions[0xAB] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xAC] = (Instruction) {"LDY abs", inst_LDY, ABS, 1};
|
||||
instructions[0xAD] = (Instruction) {"LDA abs", inst_LDA, ABS, 1};
|
||||
instructions[0xAE] = (Instruction) {"LDX abs", inst_LDX, ABS, 1};
|
||||
instructions[0xAF] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xB0] = (Instruction) {"BCS rel", inst_BCS, REL, 1};
|
||||
instructions[0xB1] = (Instruction) {"LDA ind,Y", inst_LDA, INDY, 1};
|
||||
instructions[0xB2] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xB3] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xB4] = (Instruction) {"LDY zpg,X", inst_LDY, ZPX, 1};
|
||||
instructions[0xB5] = (Instruction) {"LDA zpg,X", inst_LDA, ZPX, 1};
|
||||
instructions[0xB6] = (Instruction) {"LDX zpg,Y", inst_LDX, ZPY, 1};
|
||||
instructions[0xB7] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xB8] = (Instruction) {"CLV impl", inst_CLV, IMPL, 1};
|
||||
instructions[0xB9] = (Instruction) {"LDA abs,Y", inst_LDA, ABSY, 1};
|
||||
instructions[0xBA] = (Instruction) {"TSX impl", inst_TSX, IMPL, 1};
|
||||
instructions[0xBB] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xBC] = (Instruction) {"LDY abs,X", inst_LDY, ABSX, 1};
|
||||
instructions[0xBD] = (Instruction) {"LDA abs,X", inst_LDA, ABSX, 1};
|
||||
instructions[0xBE] = (Instruction) {"LDX abs,Y", inst_LDX, ABSY, 1};
|
||||
instructions[0xBF] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xC0] = (Instruction) {"CPY #", inst_CPY, IMM, 1};
|
||||
instructions[0xC1] = (Instruction) {"CMP X,ind", inst_CMP, XIND, 1};
|
||||
instructions[0xC2] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xC3] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xC4] = (Instruction) {"CPY zpg", inst_CPY, ZP, 1};
|
||||
instructions[0xC5] = (Instruction) {"CMP zpg", inst_CMP, ZP, 1};
|
||||
instructions[0xC6] = (Instruction) {"DEC zpg", inst_DEC, ZP, 1};
|
||||
instructions[0xC7] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xC8] = (Instruction) {"INY impl", inst_INY, IMPL, 1};
|
||||
instructions[0xC9] = (Instruction) {"CMP #", inst_CMP, IMM, 1};
|
||||
instructions[0xCA] = (Instruction) {"DEX impl", inst_DEX, IMPL, 1};
|
||||
instructions[0xCB] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xCC] = (Instruction) {"CPY abs", inst_CPY, ABS, 1};
|
||||
instructions[0xCD] = (Instruction) {"CMP abs", inst_CMP, ABS, 1};
|
||||
instructions[0xCE] = (Instruction) {"DEC abs", inst_DEC, ABS, 1};
|
||||
instructions[0xCF] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xD0] = (Instruction) {"BNE rel", inst_BNE, REL, 1};
|
||||
instructions[0xD1] = (Instruction) {"CMP ind,Y", inst_CMP, INDY, 1};
|
||||
instructions[0xD2] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xD3] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xD4] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xD5] = (Instruction) {"CMP zpg,X", inst_CMP, ZPX, 1};
|
||||
instructions[0xD6] = (Instruction) {"DEC zpg,X", inst_DEC, ZPX, 1};
|
||||
instructions[0xD7] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xD8] = (Instruction) {"CLD impl", inst_CLD, IMPL, 1};
|
||||
instructions[0xD9] = (Instruction) {"CMP abs,Y", inst_CMP, ABSY, 1};
|
||||
instructions[0xDA] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xDB] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xDC] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xDD] = (Instruction) {"CMP abs,X", inst_CMP, ABSX, 1};
|
||||
instructions[0xDE] = (Instruction) {"DEC abs,X", inst_DEC, ABSX, 1};
|
||||
instructions[0xDF] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xE0] = (Instruction) {"CPX #", inst_CPX, IMM, 1};
|
||||
instructions[0xE1] = (Instruction) {"SBC X,ind", inst_SBC, XIND, 1};
|
||||
instructions[0xE2] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xE3] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xE4] = (Instruction) {"CPX zpg", inst_CPX, ZP, 1};
|
||||
instructions[0xE5] = (Instruction) {"SBC zpg", inst_SBC, ZP, 1};
|
||||
instructions[0xE6] = (Instruction) {"INC zpg", inst_INC, ZP, 1};
|
||||
instructions[0xE7] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xE8] = (Instruction) {"INX impl", inst_INX, IMPL, 1};
|
||||
instructions[0xE9] = (Instruction) {"SBC #", inst_SBC, IMM, 1};
|
||||
instructions[0xEA] = (Instruction) {"NOP impl", inst_NOP, IMPL, 1};
|
||||
instructions[0xEB] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xEC] = (Instruction) {"CPX abs", inst_CPX, ABS, 1};
|
||||
instructions[0xED] = (Instruction) {"SBC abs", inst_SBC, ABS, 1};
|
||||
instructions[0xEE] = (Instruction) {"INC abs", inst_INC, ABS, 1};
|
||||
instructions[0xEF] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xF0] = (Instruction) {"BEQ rel", inst_BEQ, REL, 1};
|
||||
instructions[0xF1] = (Instruction) {"SBC ind,Y", inst_SBC, INDY, 1};
|
||||
instructions[0xF2] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xF3] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xF4] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xF5] = (Instruction) {"SBC zpg,X", inst_SBC, ZPX, 1};
|
||||
instructions[0xF6] = (Instruction) {"INC zpg,X", inst_INC, ZPX, 1};
|
||||
instructions[0xF7] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xF8] = (Instruction) {"SED impl", inst_SED, IMPL, 1};
|
||||
instructions[0xF9] = (Instruction) {"SBC abs,Y", inst_SBC, ABSY, 1};
|
||||
instructions[0xFA] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xFB] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xFC] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0xFD] = (Instruction) {"SBC abs,X", inst_SBC, ABSX, 1};
|
||||
instructions[0xFE] = (Instruction) {"INC abs,X", inst_INC, ABSX, 1};
|
||||
instructions[0xFF] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
instructions[0x02] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x03] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0x04] = (Instruction) {"???", inst_NOP, ZP, 3};
|
||||
instructions[0x05] = (Instruction) {"ORA zpg", inst_ORA, ZP, 3};
|
||||
instructions[0x06] = (Instruction) {"ASL zpg", inst_ASL, ZP, 5};
|
||||
instructions[0x07] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0x08] = (Instruction) {"PHP impl", inst_PHP, IMPL, 3};
|
||||
instructions[0x09] = (Instruction) {"ORA #", inst_ORA, IMM, 2};
|
||||
instructions[0x0A] = (Instruction) {"ASL A", inst_ASL, ACC, 2};
|
||||
instructions[0x0B] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x0C] = (Instruction) {"???", inst_NOP, ABS, 4};
|
||||
instructions[0x0D] = (Instruction) {"ORA abs", inst_ORA, ABS, 4};
|
||||
instructions[0x0E] = (Instruction) {"ASL abs", inst_ASL, ABS, 6};
|
||||
instructions[0x0F] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x10] = (Instruction) {"BPL rel", inst_BPL, REL, 2};
|
||||
instructions[0x11] = (Instruction) {"ORA ind,Y", inst_ORA, INDY, 5};
|
||||
instructions[0x12] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x13] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0x14] = (Instruction) {"???", inst_NOP, ZP, 4};
|
||||
instructions[0x15] = (Instruction) {"ORA zpg,X", inst_ORA, ZPX, 4};
|
||||
instructions[0x16] = (Instruction) {"ASL zpg,X", inst_ASL, ZPX, 6};
|
||||
instructions[0x17] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x18] = (Instruction) {"CLC impl", inst_CLC, IMPL, 2};
|
||||
instructions[0x19] = (Instruction) {"ORA abs,Y", inst_ORA, ABSY, 4};
|
||||
instructions[0x1A] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x1B] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0x1C] = (Instruction) {"???", inst_NOP, ABSX, 4};
|
||||
instructions[0x1D] = (Instruction) {"ORA abs,X", inst_ORA, ABSX, 4};
|
||||
instructions[0x1E] = (Instruction) {"ASL abs,X", inst_ASL, ABSX, 7};
|
||||
instructions[0x1F] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0x20] = (Instruction) {"JSR abs", inst_JSR, ABS, 6};
|
||||
instructions[0x21] = (Instruction) {"AND X,ind", inst_AND, XIND, 6};
|
||||
instructions[0x22] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x23] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0x24] = (Instruction) {"BIT zpg", inst_BIT, ZP, 3};
|
||||
instructions[0x25] = (Instruction) {"AND zpg", inst_AND, ZP, 3};
|
||||
instructions[0x26] = (Instruction) {"ROL zpg", inst_ROL, ZP, 5};
|
||||
instructions[0x27] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0x28] = (Instruction) {"PLP impl", inst_PLP, IMPL, 4};
|
||||
instructions[0x29] = (Instruction) {"AND #", inst_AND, IMM, 2};
|
||||
instructions[0x2A] = (Instruction) {"ROL A", inst_ROL, ACC, 2};
|
||||
instructions[0x2B] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x2C] = (Instruction) {"BIT abs", inst_BIT, ABS, 4};
|
||||
instructions[0x2D] = (Instruction) {"AND abs", inst_AND, ABS, 4};
|
||||
instructions[0x2E] = (Instruction) {"ROL abs", inst_ROL, ABS, 6};
|
||||
instructions[0x2F] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x30] = (Instruction) {"BMI rel", inst_BMI, REL, 2};
|
||||
instructions[0x31] = (Instruction) {"AND ind,Y", inst_AND, INDY, 5};
|
||||
instructions[0x32] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x33] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0x34] = (Instruction) {"???", inst_NOP, ZP, 4};
|
||||
instructions[0x35] = (Instruction) {"AND zpg,X", inst_AND, ZPX, 4};
|
||||
instructions[0x36] = (Instruction) {"ROL zpg,X", inst_ROL, ZPX, 6};
|
||||
instructions[0x37] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x38] = (Instruction) {"SEC impl", inst_SEC, IMPL, 2};
|
||||
instructions[0x39] = (Instruction) {"AND abs,Y", inst_AND, ABSY, 4};
|
||||
instructions[0x3A] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x3B] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0x3C] = (Instruction) {"???", inst_NOP, ABSX, 4};
|
||||
instructions[0x3D] = (Instruction) {"AND abs,X", inst_AND, ABSX, 4};
|
||||
instructions[0x3E] = (Instruction) {"ROL abs,X", inst_ROL, ABSX, 7};
|
||||
instructions[0x3F] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0x40] = (Instruction) {"RTI impl", inst_RTI, IMPL, 6};
|
||||
instructions[0x41] = (Instruction) {"EOR X,ind", inst_EOR, XIND, 6};
|
||||
instructions[0x42] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x43] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0x44] = (Instruction) {"???", inst_NOP, ZP, 3};
|
||||
instructions[0x45] = (Instruction) {"EOR zpg", inst_EOR, ZP, 3};
|
||||
instructions[0x46] = (Instruction) {"LSR zpg", inst_LSR, ZP, 5};
|
||||
instructions[0x47] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0x48] = (Instruction) {"PHA impl", inst_PHA, IMPL, 3};
|
||||
instructions[0x49] = (Instruction) {"EOR #", inst_EOR, IMM, 2};
|
||||
instructions[0x4A] = (Instruction) {"LSR A", inst_LSR, ACC, 2};
|
||||
instructions[0x4B] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x4C] = (Instruction) {"JMP abs", inst_JMP, ABS, 3};
|
||||
instructions[0x4D] = (Instruction) {"EOR abs", inst_EOR, ABS, 4};
|
||||
instructions[0x4E] = (Instruction) {"LSR abs", inst_LSR, ABS, 6};
|
||||
instructions[0x4F] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x50] = (Instruction) {"BVC rel", inst_BVC, REL, 2};
|
||||
instructions[0x51] = (Instruction) {"EOR ind,Y", inst_EOR, INDY, 5};
|
||||
instructions[0x52] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x53] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0x54] = (Instruction) {"???", inst_NOP, ZP, 4};
|
||||
instructions[0x55] = (Instruction) {"EOR zpg,X", inst_EOR, ZPX, 4};
|
||||
instructions[0x56] = (Instruction) {"LSR zpg,X", inst_LSR, ZPX, 6};
|
||||
instructions[0x57] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x58] = (Instruction) {"CLI impl", inst_CLI, IMPL, 2};
|
||||
instructions[0x59] = (Instruction) {"EOR abs,Y", inst_EOR, ABSY, 4};
|
||||
instructions[0x5A] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x5B] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0x5C] = (Instruction) {"???", inst_NOP, ABSX, 4};
|
||||
instructions[0x5D] = (Instruction) {"EOR abs,X", inst_EOR, ABSX, 4};
|
||||
instructions[0x5E] = (Instruction) {"LSR abs,X", inst_LSR, ABSX, 7};
|
||||
instructions[0x5F] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0x60] = (Instruction) {"RTS impl", inst_RTS, IMPL, 6};
|
||||
instructions[0x61] = (Instruction) {"ADC X,ind", inst_ADC, XIND, 6};
|
||||
instructions[0x62] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x63] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0x64] = (Instruction) {"???", inst_NOP, ZP, 3};
|
||||
instructions[0x65] = (Instruction) {"ADC zpg", inst_ADC, ZP, 3};
|
||||
instructions[0x66] = (Instruction) {"ROR zpg", inst_ROR, ZP, 5};
|
||||
instructions[0x67] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0x68] = (Instruction) {"PLA impl", inst_PLA, IMPL, 4};
|
||||
instructions[0x69] = (Instruction) {"ADC #", inst_ADC, IMM, 2};
|
||||
instructions[0x6A] = (Instruction) {"ROR A", inst_ROR, ACC, 2};
|
||||
instructions[0x6B] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x6C] = (Instruction) {"JMP ind", inst_JMP, JMP_IND_BUG, 5};
|
||||
instructions[0x6D] = (Instruction) {"ADC abs", inst_ADC, ABS, 4};
|
||||
instructions[0x6E] = (Instruction) {"ROR abs", inst_ROR, ABS, 6};
|
||||
instructions[0x6F] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x70] = (Instruction) {"BVS rel", inst_BVS, REL, 2};
|
||||
instructions[0x71] = (Instruction) {"ADC ind,Y", inst_ADC, INDY, 5};
|
||||
instructions[0x72] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x73] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0x74] = (Instruction) {"???", inst_NOP, ZP, 4};
|
||||
instructions[0x75] = (Instruction) {"ADC zpg,X", inst_ADC, ZPX, 4};
|
||||
instructions[0x76] = (Instruction) {"ROR zpg,X", inst_ROR, ZPX, 6};
|
||||
instructions[0x77] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x78] = (Instruction) {"SEI impl", inst_SEI, IMPL, 2};
|
||||
instructions[0x79] = (Instruction) {"ADC abs,Y", inst_ADC, ABSY, 4};
|
||||
instructions[0x7A] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x7B] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0x7C] = (Instruction) {"???", inst_NOP, ABSX, 4};
|
||||
instructions[0x7D] = (Instruction) {"ADC abs,X", inst_ADC, ABSX, 4};
|
||||
instructions[0x7E] = (Instruction) {"ROR abs,X", inst_ROR, ABSX, 7};
|
||||
instructions[0x7F] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0x80] = (Instruction) {"???", inst_NOP, IMM, 2};
|
||||
instructions[0x81] = (Instruction) {"STA X,ind", inst_STA, XIND, 6};
|
||||
instructions[0x82] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x83] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x84] = (Instruction) {"STY zpg", inst_STY, ZP, 3};
|
||||
instructions[0x85] = (Instruction) {"STA zpg", inst_STA, ZP, 3};
|
||||
instructions[0x86] = (Instruction) {"STX zpg", inst_STX, ZP, 3};
|
||||
instructions[0x87] = (Instruction) {"???", inst_NOP, IMPL, 3};
|
||||
instructions[0x88] = (Instruction) {"DEY impl", inst_DEY, IMPL, 2};
|
||||
instructions[0x89] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x8A] = (Instruction) {"TXA impl", inst_TXA, IMPL, 2};
|
||||
instructions[0x8B] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x8C] = (Instruction) {"STY abs", inst_STY, ABS, 4};
|
||||
instructions[0x8D] = (Instruction) {"STA abs", inst_STA, ABS, 4};
|
||||
instructions[0x8E] = (Instruction) {"STX abs", inst_STX, ABS, 4};
|
||||
instructions[0x8F] = (Instruction) {"???", inst_NOP, IMPL, 4};
|
||||
instructions[0x90] = (Instruction) {"BCC rel", inst_BCC, REL, 2};
|
||||
instructions[0x91] = (Instruction) {"STA ind,Y", inst_STA, INDY, 6};
|
||||
instructions[0x92] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0x93] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0x94] = (Instruction) {"STY zpg,X", inst_STY, ZPX, 4};
|
||||
instructions[0x95] = (Instruction) {"STA zpg,X", inst_STA, ZPX, 4};
|
||||
instructions[0x96] = (Instruction) {"STX zpg,Y", inst_STX, ZPY, 4};
|
||||
instructions[0x97] = (Instruction) {"???", inst_NOP, IMPL, 4};
|
||||
instructions[0x98] = (Instruction) {"TYA impl", inst_TYA, IMPL, 2};
|
||||
instructions[0x99] = (Instruction) {"STA abs,Y", inst_STA, ABSY, 5};
|
||||
instructions[0x9A] = (Instruction) {"TXS impl", inst_TXS, IMPL, 2};
|
||||
instructions[0x9B] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0x9C] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0x9D] = (Instruction) {"STA abs,X", inst_STA, ABSX, 5};
|
||||
instructions[0x9E] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0x9F] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0xA0] = (Instruction) {"LDY #", inst_LDY, IMM, 2};
|
||||
instructions[0xA1] = (Instruction) {"LDA X,ind", inst_LDA, XIND, 6};
|
||||
instructions[0xA2] = (Instruction) {"LDX #", inst_LDX, IMM, 2};
|
||||
instructions[0xA3] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0xA4] = (Instruction) {"LDY zpg", inst_LDY, ZP, 3};
|
||||
instructions[0xA5] = (Instruction) {"LDA zpg", inst_LDA, ZP, 3};
|
||||
instructions[0xA6] = (Instruction) {"LDX zpg", inst_LDX, ZP, 3};
|
||||
instructions[0xA7] = (Instruction) {"???", inst_NOP, IMPL, 3};
|
||||
instructions[0xA8] = (Instruction) {"TAY impl", inst_TAY, IMPL, 2};
|
||||
instructions[0xA9] = (Instruction) {"LDA #", inst_LDA, IMM, 2};
|
||||
instructions[0xAA] = (Instruction) {"TAX impl", inst_TAX, IMPL, 2};
|
||||
instructions[0xAB] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xAC] = (Instruction) {"LDY abs", inst_LDY, ABS, 4};
|
||||
instructions[0xAD] = (Instruction) {"LDA abs", inst_LDA, ABS, 4};
|
||||
instructions[0xAE] = (Instruction) {"LDX abs", inst_LDX, ABS, 4};
|
||||
instructions[0xAF] = (Instruction) {"???", inst_NOP, IMPL, 4};
|
||||
instructions[0xB0] = (Instruction) {"BCS rel", inst_BCS, REL, 2};
|
||||
instructions[0xB1] = (Instruction) {"LDA ind,Y", inst_LDA, INDY, 5};
|
||||
instructions[0xB2] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xB3] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0xB4] = (Instruction) {"LDY zpg,X", inst_LDY, ZPX, 4};
|
||||
instructions[0xB5] = (Instruction) {"LDA zpg,X", inst_LDA, ZPX, 4};
|
||||
instructions[0xB6] = (Instruction) {"LDX zpg,Y", inst_LDX, ZPY, 4};
|
||||
instructions[0xB7] = (Instruction) {"???", inst_NOP, IMPL, 4};
|
||||
instructions[0xB8] = (Instruction) {"CLV impl", inst_CLV, IMPL, 2};
|
||||
instructions[0xB9] = (Instruction) {"LDA abs,Y", inst_LDA, ABSY, 4};
|
||||
instructions[0xBA] = (Instruction) {"TSX impl", inst_TSX, IMPL, 2};
|
||||
instructions[0xBB] = (Instruction) {"???", inst_NOP, IMPL, 4};
|
||||
instructions[0xBC] = (Instruction) {"LDY abs,X", inst_LDY, ABSX, 4};
|
||||
instructions[0xBD] = (Instruction) {"LDA abs,X", inst_LDA, ABSX, 4};
|
||||
instructions[0xBE] = (Instruction) {"LDX abs,Y", inst_LDX, ABSY, 4};
|
||||
instructions[0xBF] = (Instruction) {"???", inst_NOP, IMPL, 4};
|
||||
instructions[0xC0] = (Instruction) {"CPY #", inst_CPY, IMM, 2};
|
||||
instructions[0xC1] = (Instruction) {"CMP X,ind", inst_CMP, XIND, 6};
|
||||
instructions[0xC2] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xC3] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0xC4] = (Instruction) {"CPY zpg", inst_CPY, ZP, 3};
|
||||
instructions[0xC5] = (Instruction) {"CMP zpg", inst_CMP, ZP, 3};
|
||||
instructions[0xC6] = (Instruction) {"DEC zpg", inst_DEC, ZP, 5};
|
||||
instructions[0xC7] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0xC8] = (Instruction) {"INY impl", inst_INY, IMPL, 2};
|
||||
instructions[0xC9] = (Instruction) {"CMP #", inst_CMP, IMM, 2};
|
||||
instructions[0xCA] = (Instruction) {"DEX impl", inst_DEX, IMPL, 2};
|
||||
instructions[0xCB] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xCC] = (Instruction) {"CPY abs", inst_CPY, ABS, 4};
|
||||
instructions[0xCD] = (Instruction) {"CMP abs", inst_CMP, ABS, 4};
|
||||
instructions[0xCE] = (Instruction) {"DEC abs", inst_DEC, ABS, 6};
|
||||
instructions[0xCF] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0xD0] = (Instruction) {"BNE rel", inst_BNE, REL, 2};
|
||||
instructions[0xD1] = (Instruction) {"CMP ind,Y", inst_CMP, INDY, 5};
|
||||
instructions[0xD2] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xD3] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0xD4] = (Instruction) {"???", inst_NOP, ZP, 4};
|
||||
instructions[0xD5] = (Instruction) {"CMP zpg,X", inst_CMP, ZPX, 4};
|
||||
instructions[0xD6] = (Instruction) {"DEC zpg,X", inst_DEC, ZPX, 6};
|
||||
instructions[0xD7] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0xD8] = (Instruction) {"CLD impl", inst_CLD, IMPL, 2};
|
||||
instructions[0xD9] = (Instruction) {"CMP abs,Y", inst_CMP, ABSY, 4};
|
||||
instructions[0xDA] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xDB] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0xDC] = (Instruction) {"???", inst_NOP, ABSX, 4};
|
||||
instructions[0xDD] = (Instruction) {"CMP abs,X", inst_CMP, ABSX, 4};
|
||||
instructions[0xDE] = (Instruction) {"DEC abs,X", inst_DEC, ABSX, 7};
|
||||
instructions[0xDF] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0xE0] = (Instruction) {"CPX #", inst_CPX, IMM, 2};
|
||||
instructions[0xE1] = (Instruction) {"SBC X,ind", inst_SBC, XIND, 6};
|
||||
instructions[0xE2] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xE3] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0xE4] = (Instruction) {"CPX zpg", inst_CPX, ZP, 3};
|
||||
instructions[0xE5] = (Instruction) {"SBC zpg", inst_SBC, ZP, 3};
|
||||
instructions[0xE6] = (Instruction) {"INC zpg", inst_INC, ZP, 5};
|
||||
instructions[0xE7] = (Instruction) {"???", inst_NOP, IMPL, 5};
|
||||
instructions[0xE8] = (Instruction) {"INX impl", inst_INX, IMPL, 2};
|
||||
instructions[0xE9] = (Instruction) {"SBC #", inst_SBC, IMM, 2};
|
||||
instructions[0xEA] = (Instruction) {"NOP impl", inst_NOP, IMPL, 2};
|
||||
instructions[0xEB] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xEC] = (Instruction) {"CPX abs", inst_CPX, ABS, 4};
|
||||
instructions[0xED] = (Instruction) {"SBC abs", inst_SBC, ABS, 4};
|
||||
instructions[0xEE] = (Instruction) {"INC abs", inst_INC, ABS, 6};
|
||||
instructions[0xEF] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0xF0] = (Instruction) {"BEQ rel", inst_BEQ, REL, 2};
|
||||
instructions[0xF1] = (Instruction) {"SBC ind,Y", inst_SBC, INDY, 5};
|
||||
instructions[0xF2] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xF3] = (Instruction) {"???", inst_NOP, IMPL, 8};
|
||||
instructions[0xF4] = (Instruction) {"???", inst_NOP, ZP, 4};
|
||||
instructions[0xF5] = (Instruction) {"SBC zpg,X", inst_SBC, ZPX, 4};
|
||||
instructions[0xF6] = (Instruction) {"INC zpg,X", inst_INC, ZPX, 6};
|
||||
instructions[0xF7] = (Instruction) {"???", inst_NOP, IMPL, 6};
|
||||
instructions[0xF8] = (Instruction) {"SED impl", inst_SED, IMPL, 2};
|
||||
instructions[0xF9] = (Instruction) {"SBC abs,Y", inst_SBC, ABSY, 4};
|
||||
instructions[0xFA] = (Instruction) {"???", inst_NOP, IMPL, 2};
|
||||
instructions[0xFB] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
instructions[0xFC] = (Instruction) {"???", inst_NOP, ABSX, 4};
|
||||
instructions[0xFD] = (Instruction) {"SBC abs,X", inst_SBC, ABSX, 4};
|
||||
instructions[0xFE] = (Instruction) {"INC abs,X", inst_INC, ABSX, 7};
|
||||
instructions[0xFF] = (Instruction) {"???", inst_NOP, IMPL, 7};
|
||||
}
|
||||
|
||||
void reset_cpu()
|
||||
void reset_cpu(int _a, int _x, int _y, int _sp, int _sr, int _pc)
|
||||
{
|
||||
A = 0;
|
||||
X = 0;
|
||||
Y = 0;
|
||||
SP = 0xFF;
|
||||
A = _a;
|
||||
X = _x;
|
||||
Y = _y;
|
||||
SP = _sp;
|
||||
|
||||
SR.byte = 0;
|
||||
SR.byte = _sr;
|
||||
SR.bits.interrupt = 1;
|
||||
SR.bits.unused = 1;
|
||||
|
||||
memcpy(&PC, &memory[RST_VEC], sizeof(PC));
|
||||
if (_pc < 0)
|
||||
memcpy(&PC, &memory[-_pc], sizeof(PC));
|
||||
else
|
||||
PC = _pc;
|
||||
|
||||
total_cycles = 0;
|
||||
}
|
||||
|
||||
int load_rom(char * filename)
|
||||
{ // TODO allow more flexible loading
|
||||
int load_rom(char * filename, int load_addr)
|
||||
{
|
||||
int loaded_size, max_size;
|
||||
|
||||
memset(memory, 0, sizeof(memory)); // clear ram first
|
||||
|
||||
FILE * fp = fopen(filename, "r");
|
||||
|
@ -857,33 +951,46 @@ int load_rom(char * filename)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!fread(&memory[0xC000], 0x4000, 1, fp)) {
|
||||
printf("Error: ROM file too short.\n");
|
||||
return -1;
|
||||
}
|
||||
max_size = 0x10000 - load_addr;
|
||||
loaded_size = (int)fread(&memory[load_addr], 1, (size_t)max_size, fp);
|
||||
fprintf(stderr, "Loaded $%04x bytes: $%04x - $%04x\n", loaded_size, load_addr, load_addr + loaded_size - 1);
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int step_cpu() // returns cycle count
|
||||
int step_cpu(int verbose) // returns cycle count
|
||||
{
|
||||
inst = instructions[memory[PC]];
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("PC=%04X OPCODE=%02X: %s\r\n", PC, memory[PC], inst.mnemonic);
|
||||
printf("A=%02X X=%02X Y=%02X SR=%02X SP=%02X\r\n", A, X, Y, SR.byte, SP);
|
||||
|
||||
/* dump memory for analysis (slows down emulation significantly) */
|
||||
|
||||
FILE * fp = fopen("memdump", "w");
|
||||
fwrite(&memory, sizeof(memory), 1, fp);
|
||||
fclose(fp);
|
||||
#endif
|
||||
|
||||
if (verbose) {
|
||||
// almost match for NES dump for easier comparison
|
||||
printf("%04X ", PC);
|
||||
if (lengths[inst.mode] == 3)
|
||||
printf("%02X %02X %02X", memory[PC], memory[PC+1], memory[PC+2]);
|
||||
else if (lengths[inst.mode] == 2)
|
||||
printf("%02X %02X ", memory[PC], memory[PC+1]);
|
||||
else
|
||||
printf("%02X ", memory[PC]);
|
||||
printf(" %-10s A:%02X X:%02X Y:%02X P:%02X SP:%02X CYC:%3d\n", inst.mnemonic, A, X, Y, SR.byte, SP, (int)((total_cycles * 3) % 341));
|
||||
}
|
||||
|
||||
jumping = 0;
|
||||
extra_cycles = 0;
|
||||
inst.function();
|
||||
if (jumping == 0) PC += lengths[inst.mode];
|
||||
|
||||
return inst.cycles;
|
||||
|
||||
// 7 cycle instructions (e.g. ROL $nnnn,X) don't have a penalty cycle for
|
||||
// crossing a page boundary.
|
||||
if (inst.cycles == 7) extra_cycles = 0;
|
||||
|
||||
total_cycles += inst.cycles + extra_cycles;
|
||||
return inst.cycles + extra_cycles;
|
||||
}
|
||||
|
||||
void save_memory(char * filename) { // dump memory for analysis (slows down emulation significantly)
|
||||
if (filename == NULL) filename = "memdump";
|
||||
FILE * fp = fopen(filename, "w");
|
||||
fwrite(&memory, sizeof(memory), 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
|
15
6502.h
15
6502.h
|
@ -4,7 +4,7 @@
|
|||
#define CPU_FREQ 4e6 // 4Mhz
|
||||
#define STEP_DURATION 10e6 // 10ms
|
||||
#define ONE_SECOND 1e9
|
||||
#define NUM_MODES 13
|
||||
#define NUM_MODES 14
|
||||
|
||||
#define NMI_VEC 0xFFFA
|
||||
#define RST_VEC 0xFFFC
|
||||
|
@ -16,6 +16,8 @@ uint8_t X;
|
|||
uint8_t Y;
|
||||
uint16_t PC;
|
||||
uint8_t SP; // points to first empty stack location
|
||||
uint8_t extra_cycles;
|
||||
uint64_t total_cycles;
|
||||
|
||||
void * read_addr;
|
||||
void * write_addr;
|
||||
|
@ -51,7 +53,8 @@ typedef enum {
|
|||
REL,
|
||||
ZP,
|
||||
ZPX,
|
||||
ZPY
|
||||
ZPY,
|
||||
JMP_IND_BUG,
|
||||
} Mode;
|
||||
|
||||
typedef struct {
|
||||
|
@ -65,8 +68,10 @@ Instruction instructions[0x100];
|
|||
|
||||
void init_tables();
|
||||
|
||||
void reset_cpu();
|
||||
void reset_cpu(int _a, int _x, int _y, int _sp, int _sr, int _pc);
|
||||
|
||||
int load_rom(char * filename);
|
||||
int load_rom(char * filename, int load_addr);
|
||||
|
||||
int step_cpu();
|
||||
int step_cpu(int verbose);
|
||||
|
||||
void save_memory(char * filename);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# NES test rom: https://wiki.nesdev.com/w/index.php/Emulator_tests
|
||||
|
||||
# other tests:
|
||||
# https://github.com/Klaus2m5/6502_65C02_functional_tests
|
||||
# https://github.com/christopherpow/nes-test-roms
|
||||
|
||||
# other simulators:
|
||||
# http://piumarta.com/software/lib6502/
|
||||
# https://github.com/dennis-chen/6502-Emu/blob/master/src/cpu.c
|
||||
|
||||
# references
|
||||
# https://wiki.nesdev.com/w/index.php/Status_flags
|
||||
# http://www.emulator101.com/6502-addressing-modes.html
|
||||
# http://nesdev.com/6502.txt
|
||||
|
||||
# now passes the NES torture test, docs at http://www.qmtpro.com/~nes/misc/nestest.txt
|
||||
# NES ROM available at http://nickmass.com/images/nestest.nes
|
||||
# log for passing test available at http://www.qmtpro.com/~nes/misc/nestest.log
|
||||
|
||||
|
||||
# Format of test log from the NES test
|
||||
# C761 4C 68 C7 JMP $C768 A:40 X:00 Y:00 P:24 SP:FB CYC:195
|
||||
|
||||
|
||||
with open('test.log') as f1, open('test/nestest-real-6502.log') as f2:
|
||||
for i, (line1, line2) in enumerate(zip(f1, f2)):
|
||||
fail = False
|
||||
if line1[0:19] != line2[0:19]:
|
||||
fail = True
|
||||
if line1[48:81] != line2[48:81]:
|
||||
fail = True
|
||||
|
||||
if fail and "NOP" not in line2:
|
||||
print("first diff: line #%d: %s\ngen: %s\nnes: %s\n" % (i, line2[0:19], line1, line2))
|
||||
print(" gen: group 1: %s group 2: %s" % (line1[0:19], line1[48:81]))
|
||||
print(" nes: group 1: %s group 2: %s" % (line2[0:19], line2[48:81]))
|
||||
break
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
echo "Running NES test"
|
||||
echo "***** Note: successful NES test will fail at the first illegal instruction, LAX at line 5259"
|
||||
./6502-emu -v -s 0xfd -r 0xc000 -c 300000 test/nestest-real-6502.rom > test.log; python compare.py
|
||||
echo
|
||||
echo "Running decimal mode test"
|
||||
./6502-emu -s 0xfd -c 3000000 -l 0x000a -r 0x1000 test/6502_functional_test+decimal.bin
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue