mirror of
https://github.com/tcarmelveilleux/dcc6502.git
synced 2024-12-26 22:30:54 +00:00
Started version 2.0
* Simplified mnemonic name lookup * Started refactor of argument parsing * Converted addressing modes to an enum * Renamed poorly named variables
This commit is contained in:
parent
34ccb70eae
commit
57e20cdf26
452
dcc6502.c
452
dcc6502.c
@ -4,7 +4,7 @@
|
|||||||
* *
|
* *
|
||||||
* This code is offered under the MIT License (MIT) *
|
* This code is offered under the MIT License (MIT) *
|
||||||
* *
|
* *
|
||||||
* Copyright (c) 2014 Tennessee Carmel-Veilleux <veilleux@tentech.ca *
|
* Copyright (c) 1998-2014 Tennessee Carmel-Veilleux <veilleux@tentech.ca> *
|
||||||
* *
|
* *
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy *
|
* Permission is hereby granted, free of charge, to any person obtaining a copy *
|
||||||
* of this software and associated documentation files (the "Software"), to deal *
|
* of this software and associated documentation files (the "Software"), to deal *
|
||||||
@ -31,23 +31,25 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define VERSION_INFO "v1.6"
|
#define VERSION_INFO "v2.0"
|
||||||
#define NUMBER_OPCODES 151
|
#define NUMBER_OPCODES 151
|
||||||
|
|
||||||
/* The 6502's 13 addressing modes */
|
/* The 6502's 13 addressing modes */
|
||||||
#define IMMED 0 /* Immediate */
|
typedef enum {
|
||||||
#define ABSOL 1 /* Absolute */
|
IMMED = 0, /* Immediate */
|
||||||
#define ZEROP 2 /* Zero Page */
|
ABSOL, /* Absolute */
|
||||||
#define IMPLI 3 /* Implied */
|
ZEROP, /* Zero Page */
|
||||||
#define INDIA 4 /* Indirect Absolute */
|
IMPLI, /* Implied */
|
||||||
#define ABSIX 5 /* Absolute indexed with X */
|
INDIA, /* Indirect Absolute */
|
||||||
#define ABSIY 6 /* Absolute indexed with Y */
|
ABSIX, /* Absolute indexed with X */
|
||||||
#define ZEPIX 7 /* Zero page indexed with X */
|
ABSIY, /* Absolute indexed with Y */
|
||||||
#define ZEPIY 8 /* Zero page indexed with Y */
|
ZEPIX, /* Zero page indexed with X */
|
||||||
#define INDIN 9 /* Indexed indirect (with X) */
|
ZEPIY, /* Zero page indexed with Y */
|
||||||
#define ININD 10 /* Indirect indexed (with Y) */
|
INDIN, /* Indexed indirect (with X) */
|
||||||
#define RELAT 11 /* Relative */
|
ININD, /* Indirect indexed (with Y) */
|
||||||
#define ACCUM 12 /* Accumulator */
|
RELAT, /* Relative */
|
||||||
|
ACCUM /* Accumulator */
|
||||||
|
} addressing_mode_e;
|
||||||
|
|
||||||
/** Some compilers don't have EOK in errno.h */
|
/** Some compilers don't have EOK in errno.h */
|
||||||
#ifndef EOK
|
#ifndef EOK
|
||||||
@ -56,232 +58,222 @@
|
|||||||
|
|
||||||
typedef struct OPcode {
|
typedef struct OPcode {
|
||||||
uint8_t number; /* Number of the opcode */
|
uint8_t number; /* Number of the opcode */
|
||||||
unsigned int name; /* Index in the name table */
|
const char *mnemonic; /* Index in the name table */
|
||||||
// FIXME: Transform toe num
|
addressing_mode_e addressing; /* Addressing mode */
|
||||||
unsigned int addressing; /* Addressing mode */
|
|
||||||
unsigned int cycles; /* Number of cycles */
|
unsigned int cycles; /* Number of cycles */
|
||||||
unsigned int cross_page; /* 1 if cross-page boundaries affect cycles */
|
unsigned int cross_page; /* 1 if cross-page boundaries affect cycles */
|
||||||
} OPcode;
|
} OPcode;
|
||||||
|
|
||||||
typedef uint16_t word;
|
typedef uint16_t word;
|
||||||
|
|
||||||
char name_table[56][4] = {
|
|
||||||
"ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI", "BNE", "BPL",
|
|
||||||
"BRK", "BVC", "BVS", "CLC", "CLD", "CLI", "CLV", "CMP", "CPX", "CPY",
|
|
||||||
"DEC", "DEX", "DEY", "EOR", "INC", "INX", "INY", "JMP", "JSR", "LDA",
|
|
||||||
"LDX", "LDY", "LSR", "NOP", "ORA", "PHA", "PHP", "PLA", "PLP", "ROL",
|
|
||||||
"ROR", "RTI", "RTS", "SBC", "SEC", "SED", "SEI", "STA", "STX", "STY",
|
|
||||||
"TAX", "TAY", "TSX", "TXA", "TXS", "TYA"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Opcode table */
|
/* Opcode table */
|
||||||
OPcode opcode_table[NUMBER_OPCODES] = {
|
OPcode opcode_table[NUMBER_OPCODES] = {
|
||||||
{0x69, 0, IMMED, 2, 1}, /* ADC */
|
{0x69, "ADC", IMMED, 2, 1}, /* ADC */
|
||||||
{0x65, 0, ZEROP, 3, 1},
|
{0x65, "ADC", ZEROP, 3, 1},
|
||||||
{0x75, 0, ZEPIX, 4, 1},
|
{0x75, "ADC", ZEPIX, 4, 1},
|
||||||
{0x6D, 0, ABSOL, 4, 1},
|
{0x6D, "ADC", ABSOL, 4, 1},
|
||||||
{0x7D, 0, ABSIX, 4, 1},
|
{0x7D, "ADC", ABSIX, 4, 1},
|
||||||
{0x79, 0, ABSIY, 4, 1},
|
{0x79, "ADC", ABSIY, 4, 1},
|
||||||
{0x61, 0, INDIN, 6, 1},
|
{0x61, "ADC", INDIN, 6, 1},
|
||||||
{0x71, 0, ININD, 5, 1},
|
{0x71, "ADC", ININD, 5, 1},
|
||||||
|
|
||||||
{0x29, 1, IMMED, 2, 1}, /* AND */
|
{0x29, "AND", IMMED, 2, 1}, /* AND */
|
||||||
{0x25, 1, ZEROP, 3, 1},
|
{0x25, "AND", ZEROP, 3, 1},
|
||||||
{0x35, 1, ZEPIX, 4, 1},
|
{0x35, "AND", ZEPIX, 4, 1},
|
||||||
{0x2D, 1, ABSOL, 4, 1},
|
{0x2D, "AND", ABSOL, 4, 1},
|
||||||
{0x3D, 1, ABSIX, 4, 1},
|
{0x3D, "AND", ABSIX, 4, 1},
|
||||||
{0x39, 1, ABSIY, 4, 1},
|
{0x39, "AND", ABSIY, 4, 1},
|
||||||
{0x21, 1, INDIN, 6, 1},
|
{0x21, "AND", INDIN, 6, 1},
|
||||||
{0x31, 1, ININD, 5, 1},
|
{0x31, "AND", ININD, 5, 1},
|
||||||
|
|
||||||
{0x0A, 2, ACCUM, 2, 0}, /* ASL */
|
{0x0A, "ASL", ACCUM, 2, 0}, /* ASL */
|
||||||
{0x06, 2, ZEROP, 5, 0},
|
{0x06, "ASL", ZEROP, 5, 0},
|
||||||
{0x16, 2, ZEPIX, 6, 0},
|
{0x16, "ASL", ZEPIX, 6, 0},
|
||||||
{0x0E, 2, ABSOL, 6, 0},
|
{0x0E, "ASL", ABSOL, 6, 0},
|
||||||
{0x1E, 2, ABSIX, 6, 0},
|
{0x1E, "ASL", ABSIX, 6, 0},
|
||||||
|
|
||||||
{0x90, 3, RELAT, 4, 1}, /* BCC */
|
{0x90, "BCC", RELAT, 4, 1}, /* BCC */
|
||||||
|
|
||||||
{0xB0, 4, RELAT, 4, 1}, /* BCS */
|
{0xB0, "BCS", RELAT, 4, 1}, /* BCS */
|
||||||
|
|
||||||
{0xF0, 5, RELAT, 4, 1}, /* BEQ */
|
{0xF0, "BEQ", RELAT, 4, 1}, /* BEQ */
|
||||||
|
|
||||||
{0x24, 6, ZEROP, 3, 0}, /* BIT */
|
{0x24, "BIT", ZEROP, 3, 0}, /* BIT */
|
||||||
{0x2C, 6, ABSOL, 4, 0},
|
{0x2C, "BIT", ABSOL, 4, 0},
|
||||||
|
|
||||||
{0x30, 7, RELAT, 4, 1}, /* BMI */
|
{0x30, "BMI", RELAT, 4, 1}, /* BMI */
|
||||||
|
|
||||||
{0xD0, 8, RELAT, 4, 1}, /* BNE */
|
{0xD0, "BNE", RELAT, 4, 1}, /* BNE */
|
||||||
|
|
||||||
{0x10, 9, RELAT, 4, 1}, /* BPL */
|
{0x10, "BPL", RELAT, 4, 1}, /* BPL */
|
||||||
|
|
||||||
{0x00, 10, IMPLI, 7, 0}, /* BRK */
|
{0x00, "BRK", IMPLI, 7, 0}, /* BRK */
|
||||||
|
|
||||||
{0x50, 11, RELAT, 4, 1}, /* BVC */
|
{0x50, "BVC", RELAT, 4, 1}, /* BVC */
|
||||||
|
|
||||||
{0x70, 12, RELAT, 4, 1}, /* BVS */
|
{0x70, "BVS", RELAT, 4, 1}, /* BVS */
|
||||||
|
|
||||||
{0x18, 13, IMPLI, 2, 0}, /* CLC */
|
{0x18, "CLC", IMPLI, 2, 0}, /* CLC */
|
||||||
|
|
||||||
{0xD8, 14, IMPLI, 2, 0}, /* CLD */
|
{0xD8, "CLD", IMPLI, 2, 0}, /* CLD */
|
||||||
|
|
||||||
{0x58, 15, IMPLI, 2, 0}, /* CLI */
|
{0x58, "CLI", IMPLI, 2, 0}, /* CLI */
|
||||||
|
|
||||||
{0xB8, 16, IMPLI, 2, 0}, /* CLV */
|
{0xB8, "CLV", IMPLI, 2, 0}, /* CLV */
|
||||||
|
|
||||||
{0xC9, 17, IMMED, 2, 0}, /* CMP */
|
{0xC9, "CMP", IMMED, 2, 0}, /* CMP */
|
||||||
{0xC5, 17, ZEROP, 3, 0},
|
{0xC5, "CMP", ZEROP, 3, 0},
|
||||||
{0xD5, 17, ZEPIX, 4, 0},
|
{0xD5, "CMP", ZEPIX, 4, 0},
|
||||||
{0xCD, 17, ABSOL, 4, 0},
|
{0xCD, "CMP", ABSOL, 4, 0},
|
||||||
{0xDD, 17, ABSIX, 4, 0},
|
{0xDD, "CMP", ABSIX, 4, 0},
|
||||||
{0xD9, 17, ABSIY, 4, 0},
|
{0xD9, "CMP", ABSIY, 4, 0},
|
||||||
{0xC1, 17, INDIN, 6, 0},
|
{0xC1, "CMP", INDIN, 6, 0},
|
||||||
{0xD1, 17, ININD, 5, 0},
|
{0xD1, "CMP", ININD, 5, 0},
|
||||||
|
|
||||||
{0xE0, 18, IMMED, 2, 0}, /* CPX */
|
{0xE0, "CPX", IMMED, 2, 0}, /* CPX */
|
||||||
{0xE4, 18, ZEROP, 3, 0},
|
{0xE4, "CPX", ZEROP, 3, 0},
|
||||||
{0xEC, 18, ABSOL, 4, 0},
|
{0xEC, "CPX", ABSOL, 4, 0},
|
||||||
|
|
||||||
{0xC0, 19, IMMED, 2, 0}, /* CPY */
|
{0xC0, "CPY", IMMED, 2, 0}, /* CPY */
|
||||||
{0xC4, 19, ZEROP, 3, 0},
|
{0xC4, "CPY", ZEROP, 3, 0},
|
||||||
{0xCC, 19, ABSOL, 4, 0},
|
{0xCC, "CPY", ABSOL, 4, 0},
|
||||||
|
|
||||||
{0xC6, 20, ZEROP, 5, 0}, /* DEC */
|
{0xC6, "DEC", ZEROP, 5, 0}, /* DEC */
|
||||||
{0xD6, 20, ZEPIX, 6, 0},
|
{0xD6, "DEC", ZEPIX, 6, 0},
|
||||||
{0xCE, 20, ABSOL, 6, 0},
|
{0xCE, "DEC", ABSOL, 6, 0},
|
||||||
{0xDE, 20, ABSIX, 6, 0},
|
{0xDE, "DEC", ABSIX, 6, 0},
|
||||||
|
|
||||||
{0xCA, 21, IMPLI, 2, 0}, /* DEX */
|
{0xCA, "DEX", IMPLI, 2, 0}, /* DEX */
|
||||||
|
|
||||||
{0x88, 22, IMPLI, 2, 0}, /* DEY */
|
{0x88, "DEY", IMPLI, 2, 0}, /* DEY */
|
||||||
|
|
||||||
{0x49, 23, IMMED, 2, 1}, /* EOR */
|
{0x49, "EOR", IMMED, 2, 1}, /* EOR */
|
||||||
{0x45, 23, ZEROP, 3, 1},
|
{0x45, "EOR", ZEROP, 3, 1},
|
||||||
{0x55, 23, ZEPIX, 4, 1},
|
{0x55, "EOR", ZEPIX, 4, 1},
|
||||||
{0x4D, 23, ABSOL, 4, 1},
|
{0x4D, "EOR", ABSOL, 4, 1},
|
||||||
{0x5D, 23, ABSIX, 4, 1},
|
{0x5D, "EOR", ABSIX, 4, 1},
|
||||||
{0x59, 23, ABSIY, 4, 1},
|
{0x59, "EOR", ABSIY, 4, 1},
|
||||||
{0x41, 23, INDIN, 6, 1},
|
{0x41, "EOR", INDIN, 6, 1},
|
||||||
{0x51, 23, ININD, 5, 1},
|
{0x51, "EOR", ININD, 5, 1},
|
||||||
|
|
||||||
{0xE6, 24, ZEROP, 5, 0}, /* INC */
|
{0xE6, "INC", ZEROP, 5, 0}, /* INC */
|
||||||
{0xF6, 24, ZEPIX, 6, 0},
|
{0xF6, "INC", ZEPIX, 6, 0},
|
||||||
{0xEE, 24, ABSOL, 6, 0},
|
{0xEE, "INC", ABSOL, 6, 0},
|
||||||
{0xFE, 24, ABSIX, 6, 0},
|
{0xFE, "INC", ABSIX, 6, 0},
|
||||||
|
|
||||||
{0xE8, 25, IMPLI, 2, 0}, /* INX */
|
{0xE8, "INX", IMPLI, 2, 0}, /* INX */
|
||||||
|
|
||||||
{0xC8, 26, IMPLI, 2, 0}, /* INY */
|
{0xC8, "INY", IMPLI, 2, 0}, /* INY */
|
||||||
|
|
||||||
{0x4C, 27, ABSOL, 3, 0}, /* JMP */
|
{0x4C, "JMP", ABSOL, 3, 0}, /* JMP */
|
||||||
{0x6C, 27, INDIA, 5, 0},
|
{0x6C, "JMP", INDIA, 5, 0},
|
||||||
|
|
||||||
{0x20, 28, ABSOL, 6, 0}, /* JSR */
|
{0x20, "JSR", ABSOL, 6, 0}, /* JSR */
|
||||||
|
|
||||||
{0xA9, 29, IMMED, 2, 1}, /* LDA */
|
{0xA9, "LDA", IMMED, 2, 1}, /* LDA */
|
||||||
{0xA5, 29, ZEROP, 3, 1},
|
{0xA5, "LDA", ZEROP, 3, 1},
|
||||||
{0xB5, 29, ZEPIX, 4, 1},
|
{0xB5, "LDA", ZEPIX, 4, 1},
|
||||||
{0xAD, 29, ABSOL, 4, 1},
|
{0xAD, "LDA", ABSOL, 4, 1},
|
||||||
{0xBD, 29, ABSIX, 4, 1},
|
{0xBD, "LDA", ABSIX, 4, 1},
|
||||||
{0xB9, 29, ABSIY, 4, 1},
|
{0xB9, "LDA", ABSIY, 4, 1},
|
||||||
{0xA1, 29, INDIN, 6, 1},
|
{0xA1, "LDA", INDIN, 6, 1},
|
||||||
{0xB1, 29, ININD, 5, 1},
|
{0xB1, "LDA", ININD, 5, 1},
|
||||||
|
|
||||||
{0xA2, 30, IMMED, 2, 1}, /* LDX */
|
{0xA2, "LDX", IMMED, 2, 1}, /* LDX */
|
||||||
{0xA6, 30, ZEROP, 3, 1},
|
{0xA6, "LDX", ZEROP, 3, 1},
|
||||||
{0xB6, 30, ZEPIY, 4, 1},
|
{0xB6, "LDX", ZEPIY, 4, 1},
|
||||||
{0xAE, 30, ABSOL, 4, 1},
|
{0xAE, "LDX", ABSOL, 4, 1},
|
||||||
{0xBE, 30, ABSIY, 4, 1},
|
{0xBE, "LDX", ABSIY, 4, 1},
|
||||||
|
|
||||||
{0xA0, 31, IMMED, 2, 1}, /* LDY */
|
{0xA0, "LDY", IMMED, 2, 1}, /* LDY */
|
||||||
{0xA4, 31, ZEROP, 3, 1},
|
{0xA4, "LDY", ZEROP, 3, 1},
|
||||||
{0xB4, 31, ZEPIX, 4, 1},
|
{0xB4, "LDY", ZEPIX, 4, 1},
|
||||||
{0xAC, 31, ABSOL, 4, 1},
|
{0xAC, "LDY", ABSOL, 4, 1},
|
||||||
{0xBC, 31, ABSIX, 4, 1},
|
{0xBC, "LDY", ABSIX, 4, 1},
|
||||||
|
|
||||||
{0x4A, 32, ACCUM, 2, 0}, /* LSR */
|
{0x4A, "LSR", ACCUM, 2, 0}, /* LSR */
|
||||||
{0x46, 32, ZEROP, 5, 0},
|
{0x46, "LSR", ZEROP, 5, 0},
|
||||||
{0x56, 32, ZEPIX, 6, 0},
|
{0x56, "LSR", ZEPIX, 6, 0},
|
||||||
{0x4E, 32, ABSOL, 6, 0},
|
{0x4E, "LSR", ABSOL, 6, 0},
|
||||||
{0x5E, 32, ABSIX, 6, 0},
|
{0x5E, "LSR", ABSIX, 6, 0},
|
||||||
|
|
||||||
{0xEA, 33, IMPLI, 2, 0}, /* NOP */
|
{0xEA, "NOP", IMPLI, 2, 0}, /* NOP */
|
||||||
|
|
||||||
{0x09, 34, IMMED, 2, 0}, /* ORA */
|
{0x09, "ORA", IMMED, 2, 0}, /* ORA */
|
||||||
{0x05, 34, ZEROP, 3, 0},
|
{0x05, "ORA", ZEROP, 3, 0},
|
||||||
{0x15, 34, ZEPIX, 4, 0},
|
{0x15, "ORA", ZEPIX, 4, 0},
|
||||||
{0x0D, 34, ABSOL, 4, 0},
|
{0x0D, "ORA", ABSOL, 4, 0},
|
||||||
{0x1D, 34, ABSIX, 4, 0},
|
{0x1D, "ORA", ABSIX, 4, 0},
|
||||||
{0x19, 34, ABSIY, 4, 0},
|
{0x19, "ORA", ABSIY, 4, 0},
|
||||||
{0x01, 34, INDIN, 6, 0},
|
{0x01, "ORA", INDIN, 6, 0},
|
||||||
{0x11, 34, ININD, 5, 0},
|
{0x11, "ORA", ININD, 5, 0},
|
||||||
|
|
||||||
{0x48, 35, IMPLI, 3, 0}, /* PHA */
|
{0x48, "PHA", IMPLI, 3, 0}, /* PHA */
|
||||||
|
|
||||||
{0x08, 36, IMPLI, 3, 0}, /* PHP */
|
{0x08, "PHP", IMPLI, 3, 0}, /* PHP */
|
||||||
|
|
||||||
{0x68, 37, IMPLI, 4, 0}, /* PLA */
|
{0x68, "PLA", IMPLI, 4, 0}, /* PLA */
|
||||||
|
|
||||||
{0x28, 38, IMPLI, 4, 0}, /* PLP */
|
{0x28, "PLP", IMPLI, 4, 0}, /* PLP */
|
||||||
|
|
||||||
{0x2A, 39, ACCUM, 2, 0}, /* ROL */
|
{0x2A, "ROL", ACCUM, 2, 0}, /* ROL */
|
||||||
{0x26, 39, ZEROP, 5, 0},
|
{0x26, "ROL", ZEROP, 5, 0},
|
||||||
{0x36, 39, ZEPIX, 6, 0},
|
{0x36, "ROL", ZEPIX, 6, 0},
|
||||||
{0x2E, 39, ABSOL, 6, 0},
|
{0x2E, "ROL", ABSOL, 6, 0},
|
||||||
{0x3E, 39, ABSIX, 6, 0},
|
{0x3E, "ROL", ABSIX, 6, 0},
|
||||||
|
|
||||||
{0x6A, 40, ACCUM, 2, 0}, /* ROR */
|
{0x6A, "ROR", ACCUM, 2, 0}, /* ROR */
|
||||||
{0x66, 40, ZEROP, 5, 0},
|
{0x66, "ROR", ZEROP, 5, 0},
|
||||||
{0x76, 40, ZEPIX, 6, 0},
|
{0x76, "ROR", ZEPIX, 6, 0},
|
||||||
{0x6E, 40, ABSOL, 6, 0},
|
{0x6E, "ROR", ABSOL, 6, 0},
|
||||||
{0x7E, 40, ABSIX, 6, 0},
|
{0x7E, "ROR", ABSIX, 6, 0},
|
||||||
|
|
||||||
{0x40, 41, IMPLI, 6, 0}, /* RTI */
|
{0x40, "RTI", IMPLI, 6, 0}, /* RTI */
|
||||||
|
|
||||||
{0x60, 42, IMPLI, 6, 0}, /* RTS */
|
{0x60, "RTS", IMPLI, 6, 0}, /* RTS */
|
||||||
|
|
||||||
{0xE9, 43, IMMED, 2, 1}, /* SBC */
|
{0xE9, "SBC", IMMED, 2, 1}, /* SBC */
|
||||||
{0xE5, 43, ZEROP, 3, 1},
|
{0xE5, "SBC", ZEROP, 3, 1},
|
||||||
{0xF5, 43, ZEPIX, 4, 1},
|
{0xF5, "SBC", ZEPIX, 4, 1},
|
||||||
{0xED, 43, ABSOL, 4, 1},
|
{0xED, "SBC", ABSOL, 4, 1},
|
||||||
{0xFD, 43, ABSIX, 4, 1},
|
{0xFD, "SBC", ABSIX, 4, 1},
|
||||||
{0xF9, 43, ABSIY, 4, 1},
|
{0xF9, "SBC", ABSIY, 4, 1},
|
||||||
{0xE1, 43, INDIN, 6, 1},
|
{0xE1, "SBC", INDIN, 6, 1},
|
||||||
{0xF1, 43, ININD, 5, 1},
|
{0xF1, "SBC", ININD, 5, 1},
|
||||||
|
|
||||||
{0x38, 44, IMPLI, 2, 0}, /* SEC */
|
{0x38, "SEC", IMPLI, 2, 0}, /* SEC */
|
||||||
|
|
||||||
{0xF8, 45, IMPLI, 2, 0}, /* SED */
|
{0xF8, "SED", IMPLI, 2, 0}, /* SED */
|
||||||
|
|
||||||
{0x78, 46, IMPLI, 2, 0}, /* SEI */
|
{0x78, "SEI", IMPLI, 2, 0}, /* SEI */
|
||||||
|
|
||||||
{0x85, 47, ZEROP, 3, 0}, /* STA */
|
{0x85, "STA", ZEROP, 3, 0}, /* STA */
|
||||||
{0x95, 47, ZEPIX, 4, 0},
|
{0x95, "STA", ZEPIX, 4, 0},
|
||||||
{0x8D, 47, ABSOL, 4, 0},
|
{0x8D, "STA", ABSOL, 4, 0},
|
||||||
{0x9D, 47, ABSIX, 4, 0},
|
{0x9D, "STA", ABSIX, 4, 0},
|
||||||
{0x99, 47, ABSIY, 4, 0},
|
{0x99, "STA", ABSIY, 4, 0},
|
||||||
{0x81, 47, INDIN, 6, 0},
|
{0x81, "STA", INDIN, 6, 0},
|
||||||
{0x91, 47, ININD, 5, 0},
|
{0x91, "STA", ININD, 5, 0},
|
||||||
|
|
||||||
{0x86, 48, ZEROP, 3, 0}, /* STX */
|
{0x86, "STX", ZEROP, 3, 0}, /* STX */
|
||||||
{0x96, 48, ZEPIY, 4, 0},
|
{0x96, "STX", ZEPIY, 4, 0},
|
||||||
{0x8E, 48, ABSOL, 4, 0},
|
{0x8E, "STX", ABSOL, 4, 0},
|
||||||
|
|
||||||
{0x84, 49, ZEROP, 3, 0}, /* STY */
|
{0x84, "STY", ZEROP, 3, 0}, /* STY */
|
||||||
{0x94, 49, ZEPIX, 4, 0},
|
{0x94, "STY", ZEPIX, 4, 0},
|
||||||
{0x8C, 49, ABSOL, 4, 0},
|
{0x8C, "STY", ABSOL, 4, 0},
|
||||||
|
|
||||||
{0xAA, 50, IMPLI, 2, 0}, /* TAX */
|
{0xAA, "TAX", IMPLI, 2, 0}, /* TAX */
|
||||||
|
|
||||||
{0xA8, 51, IMPLI, 2, 0}, /* TAY */
|
{0xA8, "TAY", IMPLI, 2, 0}, /* TAY */
|
||||||
|
|
||||||
{0xBA, 52, IMPLI, 2, 0}, /* TSX */
|
{0xBA, "TSX", IMPLI, 2, 0}, /* TSX */
|
||||||
|
|
||||||
{0x8A, 53, IMPLI, 2, 0}, /* TXA */
|
{0x8A, "TXA", IMPLI, 2, 0}, /* TXA */
|
||||||
|
|
||||||
{0x9A, 54, IMPLI, 2, 0}, /* TXS */
|
{0x9A, "TXS", IMPLI, 2, 0}, /* TXS */
|
||||||
|
|
||||||
{0x98, 55, IMPLI, 2, 0} /* TYA */
|
{0x98, "TYA", IMPLI, 2, 0} /* TYA */
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: use g_ nomenclature for globals
|
// FIXME: use g_ nomenclature for globals
|
||||||
@ -378,11 +370,12 @@ void disassemble(char *output) {
|
|||||||
int len = 0;
|
int len = 0;
|
||||||
int entry = 0;
|
int entry = 0;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
uint8_t tmp_byte1, opcode;
|
uint8_t byte_operand;
|
||||||
word tmp_word = 0;
|
word word_operand = 0;
|
||||||
uint16_t current_addr = org + PC;
|
uint16_t current_addr = org + PC;
|
||||||
|
uint8_t opcode = buffer[current_addr - org];
|
||||||
|
const char *mnemonic;
|
||||||
|
|
||||||
opcode = buffer[current_addr - org];
|
|
||||||
opcode_repr[0] = '\0';
|
opcode_repr[0] = '\0';
|
||||||
hex_dump[0] = '\0';
|
hex_dump[0] = '\0';
|
||||||
|
|
||||||
@ -410,6 +403,7 @@ void disassemble(char *output) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Opcode found in table: disassemble properly according to addressing mode
|
// Opcode found in table: disassemble properly according to addressing mode
|
||||||
|
mnemonic = opcode_table[entry].mnemonic;
|
||||||
|
|
||||||
// Set hex dump to default single address format. Will be overwritten
|
// Set hex dump to default single address format. Will be overwritten
|
||||||
// by more complex output in case of hex dump mode enabled
|
// by more complex output in case of hex dump mode enabled
|
||||||
@ -418,39 +412,39 @@ void disassemble(char *output) {
|
|||||||
switch (opcode_table[entry].addressing) {
|
switch (opcode_table[entry].addressing) {
|
||||||
case IMMED:
|
case IMMED:
|
||||||
/* Get immediate value operand */
|
/* Get immediate value operand */
|
||||||
tmp_byte1 = buffer[PC + 1];
|
byte_operand = buffer[PC + 1];
|
||||||
PC++;
|
PC++;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s #$%02x", name_table[opcode_table[entry].name], tmp_byte1);
|
sprintf(opcode_repr, "%s #$%02x", mnemonic, byte_operand);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, tmp_byte1);
|
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, byte_operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ABSOL:
|
case ABSOL:
|
||||||
/* Get absolute address operand */
|
/* Get absolute address operand */
|
||||||
tmp_word = LOAD_WORD(buffer, PC);
|
word_operand = LOAD_WORD(buffer, PC);
|
||||||
PC += 2;
|
PC += 2;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s $%02X%02X", name_table[opcode_table[entry].name], HIGH_PART(tmp_word), LOW_PART(tmp_word));
|
sprintf(opcode_repr, "%s $%02X%02X", mnemonic, HIGH_PART(word_operand), LOW_PART(word_operand));
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X%02X:", current_addr, opcode, LOW_PART(tmp_word), HIGH_PART(tmp_word));
|
sprintf(hex_dump, "$%04X> %02X %02X%02X:", current_addr, opcode, LOW_PART(word_operand), HIGH_PART(word_operand));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ZEROP:
|
case ZEROP:
|
||||||
/* Get zero page address */
|
/* Get zero page address */
|
||||||
tmp_byte1 = buffer[PC + 1];
|
byte_operand = buffer[PC + 1];
|
||||||
PC++;
|
PC++;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s $%02X", name_table[opcode_table[entry].name], tmp_byte1);
|
sprintf(opcode_repr, "%s $%02X", mnemonic, byte_operand);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, tmp_byte1);
|
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, byte_operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case IMPLI:
|
case IMPLI:
|
||||||
sprintf(opcode_repr, "%s", name_table[opcode_table[entry].name]);
|
sprintf(opcode_repr, "%s", mnemonic);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X:", current_addr, opcode);
|
sprintf(hex_dump, "$%04X> %02X:", current_addr, opcode);
|
||||||
}
|
}
|
||||||
@ -458,102 +452,102 @@ void disassemble(char *output) {
|
|||||||
break;
|
break;
|
||||||
case INDIA:
|
case INDIA:
|
||||||
/* Get indirection address */
|
/* Get indirection address */
|
||||||
tmp_word = LOAD_WORD(buffer, PC);
|
word_operand = LOAD_WORD(buffer, PC);
|
||||||
PC += 2;
|
PC += 2;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s ($%02X%02X)", name_table[opcode_table[entry].name], HIGH_PART(tmp_word), LOW_PART(tmp_word));
|
sprintf(opcode_repr, "%s ($%02X%02X)", mnemonic, HIGH_PART(word_operand), LOW_PART(word_operand));
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X%02X:", current_addr, opcode, LOW_PART(tmp_word), HIGH_PART(tmp_word));
|
sprintf(hex_dump, "$%04X> %02X %02X%02X:", current_addr, opcode, LOW_PART(word_operand), HIGH_PART(word_operand));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ABSIX:
|
case ABSIX:
|
||||||
/* Get base address */
|
/* Get base address */
|
||||||
tmp_word = LOAD_WORD(buffer, PC);
|
word_operand = LOAD_WORD(buffer, PC);
|
||||||
PC += 2;
|
PC += 2;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s $%02X%02X,X", name_table[opcode_table[entry].name], HIGH_PART(tmp_word), LOW_PART(tmp_word));
|
sprintf(opcode_repr, "%s $%02X%02X,X", mnemonic, HIGH_PART(word_operand), LOW_PART(word_operand));
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X%02X:", current_addr, opcode, LOW_PART(tmp_word), HIGH_PART(tmp_word));
|
sprintf(hex_dump, "$%04X> %02X %02X%02X:", current_addr, opcode, LOW_PART(word_operand), HIGH_PART(word_operand));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ABSIY:
|
case ABSIY:
|
||||||
/* Get baser address */
|
/* Get baser address */
|
||||||
tmp_word = LOAD_WORD(buffer, PC);
|
word_operand = LOAD_WORD(buffer, PC);
|
||||||
PC += 2;
|
PC += 2;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s $%02X%02X,Y", name_table[opcode_table[entry].name], HIGH_PART(tmp_word), LOW_PART(tmp_word));
|
sprintf(opcode_repr, "%s $%02X%02X,Y", mnemonic, HIGH_PART(word_operand), LOW_PART(word_operand));
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X%02X:", current_addr, opcode, LOW_PART(tmp_word), HIGH_PART(tmp_word));
|
sprintf(hex_dump, "$%04X> %02X %02X%02X:", current_addr, opcode, LOW_PART(word_operand), HIGH_PART(word_operand));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ZEPIX:
|
case ZEPIX:
|
||||||
/* Get zero-page base address */
|
/* Get zero-page base address */
|
||||||
tmp_byte1 = buffer[PC + 1];
|
byte_operand = buffer[PC + 1];
|
||||||
PC++;
|
PC++;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s $%02X,X", name_table[opcode_table[entry].name], tmp_byte1);
|
sprintf(opcode_repr, "%s $%02X,X", mnemonic, byte_operand);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, tmp_byte1);
|
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, byte_operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ZEPIY:
|
case ZEPIY:
|
||||||
/* Get zero-page base address */
|
/* Get zero-page base address */
|
||||||
tmp_byte1 = buffer[PC + 1];
|
byte_operand = buffer[PC + 1];
|
||||||
PC++;
|
PC++;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s $%02X,Y", name_table[opcode_table[entry].name], tmp_byte1);
|
sprintf(opcode_repr, "%s $%02X,Y", mnemonic, byte_operand);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, tmp_byte1);
|
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, byte_operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case INDIN:
|
case INDIN:
|
||||||
/* Get zero-page base address */
|
/* Get zero-page base address */
|
||||||
tmp_byte1 = buffer[PC + 1];
|
byte_operand = buffer[PC + 1];
|
||||||
PC++;
|
PC++;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s ($%02X,X)", name_table[opcode_table[entry].name], tmp_byte1);
|
sprintf(opcode_repr, "%s ($%02X,X)", mnemonic, byte_operand);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, tmp_byte1);
|
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, byte_operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ININD:
|
case ININD:
|
||||||
/* Get zero-page base address */
|
/* Get zero-page base address */
|
||||||
tmp_byte1 = buffer[PC + 1];
|
byte_operand = buffer[PC + 1];
|
||||||
PC++;
|
PC++;
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s ($%02X),Y", name_table[opcode_table[entry].name], tmp_byte1);
|
sprintf(opcode_repr, "%s ($%02X),Y", mnemonic, byte_operand);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, tmp_byte1);
|
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, byte_operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case RELAT:
|
case RELAT:
|
||||||
/* Get relative modifier */
|
/* Get relative modifier */
|
||||||
tmp_byte1 = buffer[PC + 1];
|
byte_operand = buffer[PC + 1];
|
||||||
PC++;
|
PC++;
|
||||||
|
|
||||||
// Compute displacement from first byte after full instruction.
|
// Compute displacement from first byte after full instruction.
|
||||||
tmp_word = current_addr + 2;
|
word_operand = current_addr + 2;
|
||||||
if (tmp_byte1 > 0x7Fu) {
|
if (byte_operand > 0x7Fu) {
|
||||||
tmp_word -= ((~tmp_byte1 & 0x7Fu) + 1);
|
word_operand -= ((~byte_operand & 0x7Fu) + 1);
|
||||||
} else {
|
} else {
|
||||||
tmp_word += tmp_byte1 & 0x7Fu;
|
word_operand += byte_operand & 0x7Fu;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(opcode_repr, "%s $%04X", name_table[opcode_table[entry].name], tmp_word);
|
sprintf(opcode_repr, "%s $%04X", mnemonic, word_operand);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, tmp_byte1);
|
sprintf(hex_dump, "$%04X> %02X %02X:", current_addr, opcode, byte_operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ACCUM:
|
case ACCUM:
|
||||||
sprintf(opcode_repr, "%s A", name_table[opcode_table[entry].name]);
|
sprintf(opcode_repr, "%s A", mnemonic);
|
||||||
if (hex_output) {
|
if (hex_output) {
|
||||||
sprintf(hex_dump, "$%04X> %02X:", current_addr, opcode);
|
sprintf(hex_dump, "$%04X> %02X:", current_addr, opcode);
|
||||||
}
|
}
|
||||||
@ -578,7 +572,7 @@ void disassemble(char *output) {
|
|||||||
case ABSIX:
|
case ABSIX:
|
||||||
case ABSIY:
|
case ABSIY:
|
||||||
if (nes_mode) {
|
if (nes_mode) {
|
||||||
append_nes(output, tmp_word);
|
append_nes(output, word_operand);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -600,18 +594,16 @@ void usage_helper(char *str) {
|
|||||||
// FIXME: add command line sample
|
// FIXME: add command line sample
|
||||||
// FIXME: Make these more sane and add option for decimal
|
// FIXME: Make these more sane and add option for decimal
|
||||||
void usage(void) {
|
void usage(void) {
|
||||||
usage_helper("-? -> Show this help message");
|
usage_helper("-?: Show this help message");
|
||||||
usage_helper("-oXXXX -> Set the origin (ORG), where XXXX is hexadecimal [default: 8000]");
|
usage_helper("-o ORG: Set the origin to ORG [default: 0x8000]");
|
||||||
usage_helper("-h -> Enable hex dump within disassembly");
|
usage_helper("-h: Enable hex dump within disassembly");
|
||||||
usage_helper("-mXXXX -> Only disassemble the first XXXX bytes, where XXXX is hexadecimal");
|
usage_helper("-m NUM_BYTES: Only disassemble the first NUM_BYTES bytes");
|
||||||
usage_helper("-mXXXX -> Only disassemble the first XXXX bytes, where XXXX is hexadecimal");
|
usage_helper("-n: Enable NES register annotations");
|
||||||
usage_helper("-n -> Enable NES register annotations");
|
usage_helper("-v: Get only version information");
|
||||||
usage_helper("-v -> Get only version information");
|
usage_helper("-c: Enable cycle counting annotations");
|
||||||
usage_helper("-c -> Enable cycle counting annotations");
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: DE-KLUDGIFY THIS :D
|
|
||||||
uint16_t hex2int (char *str, uint16_t dfl) {
|
uint16_t hex2int (char *str, uint16_t dfl) {
|
||||||
uint32_t tmp = 0;
|
uint32_t tmp = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user