/hacks/6502dis.c#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
typedef struct Op Op;
struct Op{
char *name;
int am;
};
enum
{
Accumulator,
Absolute,
AbsoluteX,
AbsoluteY,
Immediate,
Implicit,
Indirect,
XIndirect,
IndirectY,
Relative,
ZeroPage,
ZeroPageX,
ZeroPageY,
};
FILE *f;
unsigned int pc = 0x0000;
Op opcode[] = {
[0x00] = { "brk", Implicit },
[0x01] = { "ora", XIndirect },
[0x05] = { "ora", ZeroPage },
[0x06] = { "asl", ZeroPage },
[0x08] = { "php", Implicit },
[0x09] = { "ora", Immediate },
[0x0A] = { "asl", Accumulator },
[0x0D] = { "ora", Absolute },
[0x0E] = { "asl", Absolute },
[0x10] = { "bpl", Relative },
[0x11] = { "ora", IndirectY },
[0x15] = { "ora", ZeroPageX },
[0x16] = { "asl", ZeroPageX },
[0x18] = { "clc", Implicit },
[0x19] = { "ora", AbsoluteY },
[0x1D] = { "ora", AbsoluteX },
[0x1E] = { "asl", AbsoluteX },
[0x20] = { "jsr", Absolute },
[0x21] = { "and", XIndirect },
[0x24] = { "bit", ZeroPage },
[0x25] = { "and", ZeroPage },
[0x26] = { "rol", ZeroPage },
[0x28] = { "plp", Implicit },
[0x29] = { "and", Immediate },
[0x2A] = { "rol", Accumulator },
[0x2C] = { "bit", Absolute },
[0x2D] = { "and", Absolute },
[0x2E] = { "rol", Absolute },
[0x30] = { "bmi", Relative },
[0x31] = { "and", IndirectY },
[0x35] = { "and", ZeroPageX },
[0x36] = { "rol", ZeroPageX },
[0x38] = { "sec", Implicit },
[0x39] = { "and", AbsoluteY },
[0x3D] = { "and", AbsoluteX },
[0x3E] = { "rol", AbsoluteX },
[0x40] = { "rti", Implicit },
[0x41] = { "eor", XIndirect },
[0x45] = { "eor", ZeroPage },
[0x46] = { "lsr", ZeroPage },
[0x48] = { "pha", Implicit },
[0x49] = { "eor", Immediate },
[0x4A] = { "lsr", Accumulator },
[0x4C] = { "jmp", Absolute },
[0x4D] = { "eor", Absolute },
[0x4E] = { "lsr", Absolute },
[0x50] = { "bvc", Relative },
[0x51] = { "eor", IndirectY },
[0x55] = { "eor", ZeroPageX },
[0x56] = { "lsr", ZeroPageX },
[0x58] = { "cli", Implicit },
[0x59] = { "eor", AbsoluteY },
[0x5D] = { "eor", AbsoluteX },
[0x5E] = { "lsr", AbsoluteX },
[0x60] = { "rts", Implicit },
[0x61] = { "adc", IndirectY },
[0x65] = { "adc", ZeroPage },
[0x66] = { "ror", ZeroPage },
[0x68] = { "pla", Implicit },
[0x69] = { "adc", Immediate },
[0x6A] = { "ror", Accumulator },
[0x6C] = { "jmp", Indirect },
[0x6D] = { "adc", Absolute },
[0x6E] = { "ror", Absolute },
[0x70] = { "bvs", Relative },
[0x71] = { "adc", IndirectY },
[0x75] = { "adc", ZeroPage },
[0x76] = { "ror", ZeroPage },
[0x78] = { "sei", Implicit },
[0x79] = { "adc", AbsoluteY },
[0x7D] = { "adc", AbsoluteX },
[0x7E] = { "ror", AbsoluteX },
[0x81] = { "sta", XIndirect },
[0x84] = { "sty", ZeroPage },
[0x85] = { "sta", ZeroPage },
[0x86] = { "stx", ZeroPage },
[0x88] = { "dey", Implicit },
[0x8A] = { "txa", Implicit },
[0x8C] = { "sty", Absolute },
[0x8D] = { "sta", Absolute },
[0x8E] = { "stx", Absolute },
[0x90] = { "bcc", Relative },
[0x91] = { "sta", IndirectY },
[0x94] = { "sty", ZeroPageX },
[0x95] = { "sta", ZeroPageX },
[0x96] = { "stx", ZeroPageY },
[0x98] = { "tya", Implicit },
[0x99] = { "sta", AbsoluteY },
[0x9A] = { "txs", Implicit },
[0x9D] = { "sta", AbsoluteX },
[0xA0] = { "ldy", Immediate },
[0xA1] = { "lda", IndirectY },
[0xA2] = { "ldx", Immediate },
[0xA4] = { "ldy", ZeroPage },
[0xA5] = { "lda", ZeroPage },
[0xA6] = { "ldx", ZeroPage },
[0xA8] = { "tay", Implicit },
[0xA9] = { "lda", Absolute },
[0xAA] = { "tax", Implicit },
[0xAC] = { "ldy", Absolute },
[0xAD] = { "lda", Absolute },
[0xAE] = { "ldx", Absolute },
[0xB0] = { "bcs", Relative },
[0xB1] = { "lda", IndirectY },
[0xB4] = { "ldy", ZeroPageX },
[0xB5] = { "ldx", ZeroPageY },
[0xB6] = { "ldx", ZeroPageY },
[0xB8] = { "clv", Implicit },
[0xB9] = { "lda", AbsoluteY },
[0xBA] = { "tsx", Implicit },
[0xBC] = { "ldy", AbsoluteX },
[0xBD] = { "lda", AbsoluteX },
[0xBE] = { "ldx", AbsoluteY },
[0xC0] = { "cpy", Immediate },
[0xC1] = { "cmp", XIndirect },
[0xC4] = { "cpy", ZeroPage },
[0xC5] = { "cmp", ZeroPage },
[0xC6] = { "dec", ZeroPage },
[0xC8] = { "iny", Implicit },
[0xC9] = { "cmp", Immediate },
[0xCA] = { "dex", Implicit },
[0xCC] = { "cpy", Absolute },
[0xCD] = { "cmp", Absolute },
[0xCE] = { "dec", Absolute },
[0xD0] = { "bne", Relative },
[0xD1] = { "cmp", IndirectY },
[0xD5] = { "cmp", ZeroPageX },
[0xD6] = { "dec", ZeroPageX },
[0xD8] = { "cld", Implicit },
[0xD9] = { "cmp", AbsoluteY },
[0xDD] = { "cmp", AbsoluteX },
[0xDE] = { "dec", AbsoluteX },
[0xE0] = { "cpx", Immediate },
[0xE1] = { "sbc", XIndirect },
[0xE4] = { "cpx", ZeroPage },
[0xE5] = { "sbc", ZeroPage },
[0xE6] = { "inc", ZeroPage },
[0xE8] = { "inx", Implicit },
[0xE9] = { "sbc", Immediate },
[0xEA] = { "nop", Implicit },
[0xEC] = { "cpx", Absolute },
[0xED] = { "sbc", Absolute },
[0xEE] = { "inc", Absolute },
[0xF0] = { "beq", Relative },
[0xF1] = { "sbc", IndirectY },
[0xF5] = { "sbc", ZeroPageX },
[0xF6] = { "inc", ZeroPageX },
[0xF8] = { "sed", Implicit },
[0xF9] = { "sbc", AbsoluteY },
[0xFD] = { "sbc", AbsoluteX },
[0xFE] = { "inc", AbsoluteX },
};
int
readc(void)
{
pc++;
return fgetc(f);
}
void
putop(Op *o)
{
int lo, hi;
printf("0x%04x\t", pc-1);
switch(o->am){
case Accumulator:
case Implicit:
break;
case Immediate:
case XIndirect:
case IndirectY:
case Relative:
case ZeroPage:
case ZeroPageX:
case ZeroPageY:
lo = readc();
break;
case Absolute:
case AbsoluteX:
case AbsoluteY:
case Indirect:
hi = readc();
lo = readc();
break;
}
printf("%s", o->name);
switch(o->am){
case Accumulator:
printf(" A");
break;
case Absolute:
printf(" $%02x%02x", lo, hi);
break;
case AbsoluteX:
printf(" $%02x%02x,X", lo, hi);
break;
case AbsoluteY:
printf(" $%02x%02x,Y", lo, hi);
break;
case Immediate:
printf(" #$%02x", lo);
break;
case Implicit:
break;
case Indirect:
printf(" (%02x%02x)", lo, hi);
break;
case XIndirect:
printf(" (%02x,X)", lo);
break;
case IndirectY:
printf(" (%02x),Y", lo);
break;
case Relative:
printf(" $80%02x", (unsigned char)(lo+pc));
break;
case ZeroPage:
printf(" $%02x", lo);
break;
case ZeroPageX:
printf(" $%02x,X", lo);
break;
case ZeroPageY:
printf(" $%02x,Y", lo);
break;
}
putchar('\n');
}
int
readnum(char *s, unsigned long *val)
{
char *endp;
errno = 0;
*val = strtoul(s, &endp, 0);
if((errno!=0) || (*endp!='\0'))
return -1;
else
return 0;
}
void
usage(void)
{
fprintf(stderr, "usage: 6502dis [ -n nstart ] FILENAME\n");
exit(1);
}
int
main(int argc, char *argv[])
{
int c;
extern int optind;
Op *o;
unsigned long tmp;
while((c = getopt(argc, argv, ":s:")) != -1){
switch(c){
case 's':
if(readnum(optarg, &tmp) < 0){
fprintf(stderr, "6502dis: invalid starting address\n");
exit(1);
}else
pc = tmp;
break;
case '?':
usage();
}
}
if(optind != argc-1)
usage();
f = fopen(argv[optind], "r");
if(!f){
fprintf(stderr, "6502dis: %s: ", argv[optind]);
perror("");
exit(1);
}
while((c = readc()) != EOF){
o = &opcode[c];
if(!o->name){
printf("0x%04x\t.byte $%02x\n", pc-1, c);
continue;
}
putop(o);
}
return 0;
}