251 lines
12 KiB
JavaScript
251 lines
12 KiB
JavaScript
|
|
var Disassembler6502 = function() {
|
|
|
|
this.disassemble = function(mem, start, end, ips) {
|
|
var i;
|
|
var lines = [];
|
|
function print_func(s) {
|
|
lines[i] = s;
|
|
}
|
|
for (i = start; i < end;) {
|
|
var opcode = OPS[mem[i]];
|
|
if (!opcode) {
|
|
print_func("#" + formatHex(mem[i], 2));
|
|
i += 1;
|
|
} else {
|
|
var bytes = opcode.bytes;
|
|
var args = mem.slice(i+1, i+1+bytes);
|
|
//console.log(opcode, bytes, args);
|
|
print_func(opcode.toString.call(opcode, args));
|
|
i += bytes;
|
|
}
|
|
}
|
|
return lines;
|
|
};
|
|
|
|
function formatHex(number, len) {
|
|
if (typeof number === "undefined" || number === null || isNaN(number)) {
|
|
throw new Error("Invalid value \"" + number + "\" passed to formatHex()");
|
|
}
|
|
var str = number.toString(16).toUpperCase();
|
|
if (!len) {
|
|
if (str.length % 2 == 1) {
|
|
len = str.length+1;
|
|
}
|
|
}
|
|
while (str.length < len) {
|
|
str = "0" + str;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
function formatImmediate (args) {
|
|
return this.name + " #$" + formatHex(args[0]);
|
|
}
|
|
|
|
function formatZeroPage (args) {
|
|
return this.name + " $" + formatHex(args[0]);
|
|
}
|
|
|
|
function formatZeroPageIndexedX (args) {
|
|
return formatZeroPage.call(this, args) + ",X";
|
|
}
|
|
|
|
function formatZeroPageIndexedY (args) {
|
|
return formatZeroPage.call(this, args) + ",Y";
|
|
}
|
|
|
|
function formatAbsolute (args) {
|
|
return this.name + " $" + formatHex(args[1], 2) + formatHex(args[0], 2);
|
|
}
|
|
|
|
function formatAbsoluteIndexedX (args) {
|
|
return formatAbsolute.call(this, args) + ",X";
|
|
}
|
|
|
|
function formatAbsoluteIndexedY (args) {
|
|
return formatAbsolute.call(this, args) + ",Y";
|
|
}
|
|
|
|
function formatIndirect (args) {
|
|
return this.name + " ($" + formatHex(args[1], 2) + formatHex(args[0], 2) + ")";
|
|
}
|
|
|
|
function formatIndirectIndexedX (args) {
|
|
return this.name + " ($" + formatHex(args[0], 2) + ",X)";
|
|
}
|
|
|
|
function formatIndirectIndexedY (args) {
|
|
return this.name + " ($" + formatHex(args[0], 2) + "),Y";
|
|
}
|
|
|
|
function formatName() {
|
|
return this.name;
|
|
}
|
|
|
|
function formatRelative (args) {
|
|
return this.name + " $" + formatHex(args[0], 2);
|
|
}
|
|
|
|
function formatAccumulator (args) {
|
|
return this.name + " A";
|
|
}
|
|
|
|
|
|
|
|
var OPS = {
|
|
0xA0 : { name: "LDY", bytes: 2, toString: formatImmediate },
|
|
0xA4 : { name: "LDY", bytes: 2, toString: formatZeroPage },
|
|
0xB4 : { name: "LDY", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0xAC : { name: "LDY", bytes: 3, toString: formatAbsolute },
|
|
0xBC : { name: "LDY", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0xA2 : { name: "LDX", bytes: 2, toString: formatImmediate },
|
|
0xA6 : { name: "LDX", bytes: 2, toString: formatZeroPage },
|
|
0xB6 : { name: "LDX", bytes: 2, toString: formatZeroPageIndexedY },
|
|
0xAE : { name: "LDX", bytes: 3, toString: formatAbsolute },
|
|
0xBE : { name: "LDX", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0xA9 : { name: "LDA", bytes: 2, toString: formatImmediate },
|
|
0xA5 : { name: "LDA", bytes: 2, toString: formatZeroPage },
|
|
0xB5 : { name: "LDA", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0xAD : { name: "LDA", bytes: 3, toString: formatAbsolute },
|
|
0xBD : { name: "LDA", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0xB9 : { name: "LDA", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0xA1 : { name: "LDA", bytes: 2, toString: formatIndirectIndexedX },
|
|
0xB1 : { name: "LDA", bytes: 2, toString: formatIndirectIndexedY },
|
|
0x86 : { name: "STX", bytes: 2, toString: formatZeroPage },
|
|
0x96 : { name: "STX", bytes: 2, toString: formatZeroPageIndexedY },
|
|
0x8E : { name: "STX", bytes: 3, toString: formatAbsolute },
|
|
0x84 : { name: "STY", bytes: 2, toString: formatZeroPage },
|
|
0x94 : { name: "STY", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x8C : { name: "STY", bytes: 3, toString: formatAbsolute },
|
|
0x85 : { name: "STA", bytes: 2, toString: formatZeroPage },
|
|
0x95 : { name: "STA", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x8D : { name: "STA", bytes: 3, toString: formatAbsolute },
|
|
0x9D : { name: "STA", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x99 : { name: "STA", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0x81 : { name: "STA", bytes: 2, toString: formatIndirectIndexedX },
|
|
0x91 : { name: "STA", bytes: 2, toString: formatIndirectIndexedY },
|
|
0xE8 : { name: "INX", bytes: 1, toString: formatName },
|
|
0xC8 : { name: "INY", bytes: 1, toString: formatName },
|
|
0xCA : { name: "DEX", bytes: 1, toString: formatName },
|
|
0x88 : { name: "DEY", bytes: 1, toString: formatName },
|
|
0xE6 : { name: "INC", bytes: 2, toString: formatZeroPage },
|
|
0xF6 : { name: "INC", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0xEE : { name: "INC", bytes: 3, toString: formatAbsolute },
|
|
0xFE : { name: "INC", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0xC6 : { name: "DEC", bytes: 2, toString: formatZeroPage },
|
|
0xD6 : { name: "DEC", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0xCE : { name: "DEC", bytes: 3, toString: formatAbsolute },
|
|
0xDE : { name: "DEC", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x38 : { name: "SEC", bytes: 1, toString: formatName },
|
|
0xF8 : { name: "SED", bytes: 1, toString: formatName },
|
|
0x78 : { name: "SEI", bytes: 1, toString: formatName },
|
|
0x18 : { name: "CLC", bytes: 1, toString: formatName },
|
|
0xD8 : { name: "CLD", bytes: 1, toString: formatName },
|
|
0x58 : { name: "CLI", bytes: 1, toString: formatName },
|
|
0xB8 : { name: "CLV", bytes: 1, toString: formatName },
|
|
0xAA : { name: "TAX", bytes: 1, toString: formatName },
|
|
0x8A : { name: "TXA", bytes: 1, toString: formatName },
|
|
0xA8 : { name: "TAY", bytes: 1, toString: formatName },
|
|
0x98 : { name: "TYA", bytes: 1, toString: formatName },
|
|
0xBA : { name: "TSX", bytes: 1, toString: formatName },
|
|
0x9A : { name: "TXS", bytes: 1, toString: formatName },
|
|
0x48 : { name: "PHA", bytes: 1, toString: formatName },
|
|
0x08 : { name: "PHP", bytes: 1, toString: formatName },
|
|
0x68 : { name: "PLA", bytes: 1, toString: formatName },
|
|
0x28 : { name: "PLP", bytes: 1, toString: formatName },
|
|
0x29 : { name: "AND", bytes: 2, toString: formatImmediate },
|
|
0x25 : { name: "AND", bytes: 2, toString: formatZeroPage },
|
|
0x35 : { name: "AND", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x2D : { name: "AND", bytes: 3, toString: formatAbsolute },
|
|
0x3D : { name: "AND", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x39 : { name: "AND", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0x21 : { name: "AND", bytes: 2, toString: formatIndirectIndexedX },
|
|
0x31 : { name: "AND", bytes: 2, toString: formatIndirectIndexedY },
|
|
0x09 : { name: "ORA", bytes: 2, toString: formatImmediate },
|
|
0x05 : { name: "ORA", bytes: 2, toString: formatZeroPage },
|
|
0x15 : { name: "ORA", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x0D : { name: "ORA", bytes: 3, toString: formatAbsolute },
|
|
0x1D : { name: "ORA", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x19 : { name: "ORA", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0x01 : { name: "ORA", bytes: 2, toString: formatIndirectIndexedX },
|
|
0x11 : { name: "ORA", bytes: 2, toString: formatIndirectIndexedY },
|
|
0x49 : { name: "EOR", bytes: 2, toString: formatImmediate },
|
|
0x45 : { name: "EOR", bytes: 2, toString: formatZeroPage },
|
|
0x55 : { name: "EOR", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x4D : { name: "EOR", bytes: 3, toString: formatAbsolute },
|
|
0x5D : { name: "EOR", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x59 : { name: "EOR", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0x41 : { name: "EOR", bytes: 2, toString: formatIndirectIndexedX },
|
|
0x51 : { name: "EOR", bytes: 2, toString: formatIndirectIndexedY },
|
|
0x4C : { name: "JMP", bytes: 3, toString: formatAbsolute },
|
|
0x6C : { name: "JMP", bytes: 3, toString: formatIndirect },
|
|
0x20 : { name: "JSR", bytes: 3, toString: formatAbsolute },
|
|
0x60 : { name: "RTS", bytes: 1, toString: formatName },
|
|
0x40 : { name: "RTI", bytes: 1, toString: formatName },
|
|
0x90 : { name: "BCC", bytes: 2, toString: formatRelative },
|
|
0xB0 : { name: "BCS", bytes: 2, toString: formatRelative },
|
|
0xF0 : { name: "BEQ", bytes: 2, toString: formatRelative },
|
|
0xD0 : { name: "BNE", bytes: 2, toString: formatRelative },
|
|
0x10 : { name: "BPL", bytes: 2, toString: formatRelative },
|
|
0x30 : { name: "BMI", bytes: 2, toString: formatRelative },
|
|
0x50 : { name: "BVC", bytes: 2, toString: formatRelative },
|
|
0x70 : { name: "BVS", bytes: 2, toString: formatRelative },
|
|
0x2A : { name: "ROL", bytes: 1, toString: formatAccumulator },
|
|
0x26 : { name: "ROL", bytes: 2, toString: formatZeroPage },
|
|
0x36 : { name: "ROL", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x2E : { name: "ROL", bytes: 3, toString: formatAbsolute },
|
|
0x3E : { name: "ROL", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x6A : { name: "ROR", bytes: 1, toString: formatAccumulator },
|
|
0x66 : { name: "ROR", bytes: 2, toString: formatZeroPage },
|
|
0x76 : { name: "ROR", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x6E : { name: "ROR", bytes: 3, toString: formatAbsolute },
|
|
0x7E : { name: "ROR", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x4A : { name: "LSR", bytes: 1, toString: formatAccumulator },
|
|
0x46 : { name: "LSR", bytes: 2, toString: formatZeroPage },
|
|
0x56 : { name: "LSR", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x4E : { name: "LSR", bytes: 3, toString: formatAbsolute },
|
|
0x5E : { name: "LSR", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x0A : { name: "ASL", bytes: 1, toString: formatAccumulator },
|
|
0x06 : { name: "ASL", bytes: 2, toString: formatZeroPage },
|
|
0x16 : { name: "ASL", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x0E : { name: "ASL", bytes: 3, toString: formatAbsolute },
|
|
0x1E : { name: "ASL", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0xC9 : { name: "CMP", bytes: 2, toString: formatImmediate },
|
|
0xC5 : { name: "CMP", bytes: 2, toString: formatZeroPage },
|
|
0xD5 : { name: "CMP", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0xCD : { name: "CMP", bytes: 3, toString: formatAbsolute },
|
|
0xDD : { name: "CMP", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0xD9 : { name: "CMP", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0xC1 : { name: "CMP", bytes: 2, toString: formatIndirectIndexedX },
|
|
0xD1 : { name: "CMP", bytes: 2, toString: formatIndirectIndexedY },
|
|
0xE0 : { name: "CPX", bytes: 2, toString: formatImmediate },
|
|
0xE4 : { name: "CPX", bytes: 2, toString: formatZeroPage },
|
|
0xEC : { name: "CPX", bytes: 3, toString: formatAbsolute },
|
|
0xC0 : { name: "CPY", bytes: 2, toString: formatImmediate },
|
|
0xC4 : { name: "CPY", bytes: 2, toString: formatZeroPage },
|
|
0xCC : { name: "CPY", bytes: 3, toString: formatAbsolute },
|
|
0x24 : { name: "BIT", bytes: 2, toString: formatZeroPage },
|
|
0x2C : { name: "BIT", bytes: 3, toString: formatAbsolute },
|
|
0x69 : { name: "ADC", bytes: 2, toString: formatImmediate },
|
|
0x65 : { name: "ADC", bytes: 2, toString: formatZeroPage },
|
|
0x75 : { name: "ADC", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0x6D : { name: "ADC", bytes: 3, toString: formatAbsolute },
|
|
0x7D : { name: "ADC", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0x79 : { name: "ADC", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0x61 : { name: "ADC", bytes: 2, toString: formatIndirectIndexedX },
|
|
0x71 : { name: "ADC", bytes: 2, toString: formatIndirectIndexedY },
|
|
0xE9 : { name: "SBC", bytes: 2, toString: formatImmediate },
|
|
0xE5 : { name: "SBC", bytes: 2, toString: formatZeroPage },
|
|
0xF5 : { name: "SBC", bytes: 2, toString: formatZeroPageIndexedX },
|
|
0xED : { name: "SBC", bytes: 3, toString: formatAbsolute },
|
|
0xFD : { name: "SBC", bytes: 3, toString: formatAbsoluteIndexedX },
|
|
0xF9 : { name: "SBC", bytes: 3, toString: formatAbsoluteIndexedY },
|
|
0xE1 : { name: "SBC", bytes: 2, toString: formatIndirectIndexedX },
|
|
0xF1 : { name: "SBC", bytes: 2, toString: formatIndirectIndexedY },
|
|
0xEA : { name: "NOP", bytes: 1, toString: formatName },
|
|
0x00 : { name: "BRK", bytes: 1, toString: formatName },
|
|
};
|
|
|
|
}
|