disassemble every single opcode

This commit is contained in:
2025-07-13 19:54:57 +02:00
parent 212f5aa9cc
commit b24fc558cc
3 changed files with 313 additions and 20 deletions

View File

@@ -1,4 +1,6 @@
#!/bin/bash #!/bin/bash
set -xe set -xe
cc -O3 -o chip8 chip8.c -L/usr/local/lib/libraylib.a -lraylib -lm CFLAGS="-Wall -Wextra -Wpedantic -std=c99 -O3"
cc -O3 -o mos6502 mos6502.c
cc $CFLAGS -o chip8 chip8.c -L/usr/local/lib/libraylib.a -lraylib -lm
cc $CFLAGS -o mos6502 mos6502.c

View File

@@ -37,7 +37,7 @@ typedef struct CHIP8 {
uint8_t *display; uint8_t *display;
} CHIP8; } CHIP8;
CHIP8 chip8_create() { CHIP8 chip8_create(void) {
static const uint8_t fonts[] = { static const uint8_t fonts[] = {
0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
0x20, 0x60, 0x20, 0x20, 0x70, // 1 0x20, 0x60, 0x20, 0x20, 0x70, // 1
@@ -284,7 +284,7 @@ void chip8_step(CHIP8 *c) {
c->reg[x] = c->reg[y] - c->reg[x]; c->reg[x] = c->reg[y] - c->reg[x];
break; break;
case 0xE: case 0xE:
c->reg[0xF] = (c->reg[x] & 0b10000000) >> 7; c->reg[0xF] = (c->reg[x] & 0x80) >> 7;
c->reg[x] <<= 1; c->reg[x] <<= 1;
break; break;
default: default:
@@ -309,7 +309,7 @@ void chip8_step(CHIP8 *c) {
c->reg[0xF] = 0; c->reg[0xF] = 0;
for (size_t row = 0; row < n; row++) { for (size_t row = 0; row < n; row++) {
for (int col = 0; col < 8; col++) { for (int col = 0; col < 8; col++) {
if ((c->memory[c->I + row] & (0b10000000 >> col)) != 0) { if ((c->memory[c->I + row] & (0x80 >> col)) != 0) {
size_t pixel_x = (c->reg[x] + col) % 64; size_t pixel_x = (c->reg[x] + col) % 64;
size_t pixel_y = (c->reg[y] + row) % 32; size_t pixel_y = (c->reg[y] + row) % 32;
size_t offset = pixel_x + (pixel_y * 64); size_t offset = pixel_x + (pixel_y * 64);
@@ -441,4 +441,4 @@ int main(int argc, char *argv[]) {
EndDrawing(); EndDrawing();
} }
} }

319
mos6502.c
View File

@@ -20,15 +20,15 @@ typedef struct MOS6502 {
// uint8_t P; // uint8_t P;
} MOS6502; } MOS6502;
MOS6502 mos6502_create() { MOS6502 mos6502_create(void) {
MOS6502 m = {0}; MOS6502 m = {0};
m.pc = 0x600; m.pc = 0x600;
m.memory = calloc(1, 1 << 16); m.memory = calloc(1, 1 << 16);
return m; return m;
} }
void mos6502_disassemble(MOS6502 *m, size_t ins_count) { void mos6502_disassemble(MOS6502 *m, size_t program_size) {
for (size_t i = 0; i < ins_count; i++) { while (m->pc < 0x600 + program_size) {
printf("%04X: ", m->pc); printf("%04X: ", m->pc);
uint8_t op = m->memory[m->pc++]; uint8_t op = m->memory[m->pc++];
@@ -36,6 +36,15 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0x00: { case 0x00: {
printf("BRK\n"); printf("BRK\n");
} break; } break;
case 0x01: {
printf("ORA ($%02X,X)\n", m->memory[m->pc++]);
} break;
case 0x05: {
printf("ORA $%02X\n", m->memory[m->pc++]);
} break;
case 0x06: {
printf("ASL $%02X\n", m->memory[m->pc++]);
} break;
case 0x08: { case 0x08: {
printf("PHP\n"); printf("PHP\n");
} break; } break;
@@ -45,27 +54,75 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0x0A: { case 0x0A: {
printf("ASL A\n"); printf("ASL A\n");
} break; } break;
case 0x0D: {
READ_ADDR();
printf("ORA $%04X\n", addr);
} break;
case 0x0E: {
READ_ADDR();
printf("ASL $%04X\n", addr);
} break;
case 0x10: { case 0x10: {
int8_t offset = m->memory[m->pc++]; int8_t offset = m->memory[m->pc++];
printf("BPL $%04X\n", m->pc + offset); printf("BPL $%04X\n", m->pc + offset);
} break; } break;
case 0x11: {
printf("ORA ($%02X),Y\n", m->memory[m->pc++]);
} break;
case 0x15: {
printf("ORA $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x16: {
printf("ASL $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x18: { case 0x18: {
printf("CLC\n"); printf("CLC\n");
} break; } break;
case 0x19: {
READ_ADDR();
printf("ORA $%04X,Y\n", addr);
} break;
case 0x1D: {
READ_ADDR();
printf("ORA $%04X,X\n", addr);
} break;
case 0x1E: {
READ_ADDR();
printf("ASL $%04X,X\n", addr);
} break;
case 0x20: { case 0x20: {
READ_ADDR(); READ_ADDR();
printf("JSR $%04X\n", addr); printf("JSR $%04X\n", addr);
} break; } break;
case 0x21: {
printf("AND ($%02X,X)\n", m->memory[m->pc++]);
} break;
case 0x24: {
printf("BIT $%02X\n", m->memory[m->pc++]);
} break;
case 0x25: {
printf("AND $%02X\n", m->memory[m->pc++]);
} break;
case 0x26: {
printf("ROL $%02X\n", m->memory[m->pc++]);
} break;
case 0x28: { case 0x28: {
printf("PLP\n"); printf("PLP\n");
} break; } break;
case 0x29: { case 0x29: {
printf("AND #$%02X\n", m->memory[m->pc++]); printf("AND #$%02X\n", m->memory[m->pc++]);
} break; } break;
case 0x2A: {
printf("ROL A\n");
} break;
case 0x2C: { case 0x2C: {
READ_ADDR(); READ_ADDR();
printf("BIT $%04X\n", addr); printf("BIT $%04X\n", addr);
} break; } break;
case 0x2D: {
READ_ADDR();
printf("AND $%04X\n", addr);
} break;
case 0x2E: { case 0x2E: {
READ_ADDR(); READ_ADDR();
printf("ROL $%04X\n", addr); printf("ROL $%04X\n", addr);
@@ -74,15 +131,41 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
int8_t offset = m->memory[m->pc++]; int8_t offset = m->memory[m->pc++];
printf("BMI $%04X\n", m->pc + offset); printf("BMI $%04X\n", m->pc + offset);
} break; } break;
case 0x31: {
printf("AND ($%02X),Y\n", m->memory[m->pc++]);
} break;
case 0x35: {
printf("AND $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x36: {
printf("ROL $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x38: { case 0x38: {
printf("SEC\n"); printf("SEC\n");
} break; } break;
case 0x39: {
READ_ADDR();
printf("AND $%04X,Y\n", addr);
} break;
case 0x3D: {
READ_ADDR();
printf("AND $%04X,X\n", addr);
} break;
case 0x3E: {
READ_ADDR();
printf("ROL $%04X,X\n", addr);
} break;
case 0x40: { case 0x40: {
printf("RTI\n"); printf("RTI\n");
} break; } break;
case 0x4C: { case 0x41: {
READ_ADDR(); printf("EOR ($%02X,X)\n", m->memory[m->pc++]);
printf("JMP $%04X\n", addr); } break;
case 0x45: {
printf("EOR $%02X\n", m->memory[m->pc++]);
} break;
case 0x46: {
printf("LSR $%02X\n", m->memory[m->pc++]);
} break; } break;
case 0x48: { case 0x48: {
printf("PHA\n"); printf("PHA\n");
@@ -93,19 +176,75 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0x4A: { case 0x4A: {
printf("LSR A\n"); printf("LSR A\n");
} break; } break;
case 0x4C: {
READ_ADDR();
printf("JMP $%04X\n", addr);
} break;
case 0x4D: {
READ_ADDR();
printf("EOR $%04X\n", addr);
} break;
case 0x4E: {
READ_ADDR();
printf("LSR $%04X\n", addr);
} break;
case 0x50: { case 0x50: {
int8_t offset = m->memory[m->pc++]; int8_t offset = m->memory[m->pc++];
printf("BVC $%04X\n", m->pc + offset); printf("BVC $%04X\n", m->pc + offset);
} break; } break;
case 0x51: {
printf("EOR ($%02X),Y\n", m->memory[m->pc++]);
} break;
case 0x55: {
printf("EOR $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x56: {
printf("LSR $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x58: {
printf("CLI\n");
} break;
case 0x59: {
READ_ADDR();
printf("EOR $%04X,Y\n", addr);
} break;
case 0x5D: {
READ_ADDR();
printf("EOR $%04X,X\n", addr);
} break;
case 0x5E: {
READ_ADDR();
printf("LSR $%04X,X\n", addr);
} break;
case 0x60: { case 0x60: {
printf("RTS\n"); printf("RTS\n");
} break; } break;
case 0x61: {
printf("ADC ($%02X,X)\n", m->memory[m->pc++]);
} break;
case 0x65: {
printf("ADC $%02X\n", m->memory[m->pc++]);
} break;
case 0x66: {
printf("ROR $%02X\n", m->memory[m->pc++]);
} break;
case 0x68: { case 0x68: {
printf("PLA\n"); printf("PLA\n");
} break; } break;
case 0x69: { case 0x69: {
printf("ADC #$%02X\n", m->memory[m->pc++]); printf("ADC #$%02X\n", m->memory[m->pc++]);
} break; } break;
case 0x6A: {
printf("ROR A\n");
} break;
case 0x6C: {
READ_ADDR();
printf("JMP ($%04X)\n", addr);
} break;
case 0x6D: {
READ_ADDR();
printf("ADC $%04X\n", addr);
} break;
case 0x6E: { case 0x6E: {
READ_ADDR(); READ_ADDR();
printf("ROR $%04X\n", addr); printf("ROR $%04X\n", addr);
@@ -114,16 +253,42 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
int8_t offset = m->memory[m->pc++]; int8_t offset = m->memory[m->pc++];
printf("BVS $%04X\n", m->pc + offset); printf("BVS $%04X\n", m->pc + offset);
} break; } break;
case 0x71: {
printf("ADC ($%02X),Y\n", m->memory[m->pc++]);
} break;
case 0x75: {
printf("ADC $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x76: {
printf("ROR $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x78: { case 0x78: {
printf("SEI\n"); printf("SEI\n");
} break; } break;
case 0x79: {
READ_ADDR();
printf("ADC $%04X,Y\n", addr);
} break;
case 0x7E: {
READ_ADDR();
printf("ROR $%04X,X\n", addr);
} break;
case 0x7D: { case 0x7D: {
READ_ADDR(); READ_ADDR();
printf("ADC $%04X,X\n", addr); printf("ADC $%04X,X\n", addr);
} break; } break;
case 0x81: {
printf("STA ($%02X,X)\n", m->memory[m->pc++]);
} break;
case 0x84: {
printf("STY $%02X\n", m->memory[m->pc++]);
} break;
case 0x85: { case 0x85: {
printf("STA $%02X\n", m->memory[m->pc++]); printf("STA $%02X\n", m->memory[m->pc++]);
} break; } break;
case 0x86: {
printf("STX $%02X\n", m->memory[m->pc++]);
} break;
case 0x88: { case 0x88: {
printf("DEY\n"); printf("DEY\n");
} break; } break;
@@ -149,6 +314,15 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0x91: { case 0x91: {
printf("STA ($%02X),Y\n", m->memory[m->pc++]); printf("STA ($%02X),Y\n", m->memory[m->pc++]);
} break; } break;
case 0x94: {
printf("STY $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x95: {
printf("STA $%02X,X\n", m->memory[m->pc++]);
} break;
case 0x96: {
printf("STX $%02X,Y\n", m->memory[m->pc++]);
} break;
case 0x98: { case 0x98: {
printf("TYA\n"); printf("TYA\n");
} break; } break;
@@ -172,6 +346,15 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0xA2: { case 0xA2: {
printf("LDX #$%02X\n", m->memory[m->pc++]); printf("LDX #$%02X\n", m->memory[m->pc++]);
} break; } break;
case 0xA4: {
printf("LDY $%02X\n", m->memory[m->pc++]);
} break;
case 0xA5: {
printf("LDA $%02X\n", m->memory[m->pc++]);
} break;
case 0xA6: {
printf("LDX $%02X\n", m->memory[m->pc++]);
} break;
case 0xA8: { case 0xA8: {
printf("TAY\n"); printf("TAY\n");
} break; } break;
@@ -181,10 +364,18 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0xAA: { case 0xAA: {
printf("TAX\n"); printf("TAX\n");
} break; } break;
case 0xAC: {
READ_ADDR();
printf("LDY $%04X\n", addr);
} break;
case 0xAD: { case 0xAD: {
READ_ADDR(); READ_ADDR();
printf("LDA $%04X\n", addr); printf("LDA $%04X\n", addr);
} break; } break;
case 0xAE: {
READ_ADDR();
printf("LDX $%04X\n", addr);
} break;
case 0xB0: { case 0xB0: {
int8_t offset = m->memory[m->pc++]; int8_t offset = m->memory[m->pc++];
printf("BCS $%04X\n", m->pc + offset); printf("BCS $%04X\n", m->pc + offset);
@@ -192,21 +383,51 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0xB1: { case 0xB1: {
printf("LDA ($%02X,Y)\n", m->memory[m->pc++]); printf("LDA ($%02X,Y)\n", m->memory[m->pc++]);
} break; } break;
case 0xB4: {
printf("LDY $%02X,X\n", m->memory[m->pc++]);
} break;
case 0xB5: {
printf("LDA $%02X,X\n", m->memory[m->pc++]);
} break;
case 0xB6: {
printf("LDX $%02X,Y\n", m->memory[m->pc++]);
} break;
case 0xB8: { case 0xB8: {
printf("CLV\n"); printf("CLV\n");
} break; } break;
case 0xB9: {
READ_ADDR();
printf("LDA $%04X,Y\n", addr);
} break;
case 0xBA: { case 0xBA: {
printf("TSX\n"); printf("TSX\n");
} break; } break;
case 0xBC: {
READ_ADDR();
printf("LDY $%04X,X\n", addr);
} break;
case 0xBD: { case 0xBD: {
READ_ADDR(); READ_ADDR();
printf("LDA $%04X,X\n", addr); printf("LDA $%04X,X\n", addr);
} break; } break;
case 0xBE: {
READ_ADDR();
printf("LDX $%04X,Y\n", addr);
} break;
case 0xC0: { case 0xC0: {
printf("CPY #$%02X\n", m->memory[m->pc++]); printf("CPY #$%02X\n", m->memory[m->pc++]);
} break; } break;
case 0xCA: { case 0xC1: {
printf("DEX\n"); printf("CMP ($%02X,X)\n", m->memory[m->pc++]);
} break;
case 0xC4: {
printf("CPY $%02X\n", m->memory[m->pc++]);
} break;
case 0xC5: {
printf("CMP $%02X\n", m->memory[m->pc++]);
} break;
case 0xC6: {
printf("DEC $%02X\n", m->memory[m->pc++]);
} break; } break;
case 0xC8: { case 0xC8: {
printf("INY\n"); printf("INY\n");
@@ -214,6 +435,17 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0xC9: { case 0xC9: {
printf("CMP #$%02X\n", m->memory[m->pc++]); printf("CMP #$%02X\n", m->memory[m->pc++]);
} break; } break;
case 0xCA: {
printf("DEX\n");
} break;
case 0xCC: {
READ_ADDR();
printf("CPY $%04X\n", addr);
} break;
case 0xCD: {
READ_ADDR();
printf("CMP $%04X\n", addr);
} break;
case 0xCE: { case 0xCE: {
READ_ADDR(); READ_ADDR();
printf("DEC $%04X\n", addr); printf("DEC $%04X\n", addr);
@@ -222,12 +454,42 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
int8_t offset = m->memory[m->pc++]; int8_t offset = m->memory[m->pc++];
printf("BNE $%04X\n", m->pc + offset); printf("BNE $%04X\n", m->pc + offset);
} break; } break;
case 0xD1: {
printf("CMP ($%02X),Y\n", m->memory[m->pc++]);
} break;
case 0xD5: {
printf("CMP $%02X,X\n", m->memory[m->pc++]);
} break;
case 0xD6: {
printf("DEC $%02X,X\n", m->memory[m->pc++]);
} break;
case 0xD8: { case 0xD8: {
printf("CLD\n"); printf("CLD\n");
} break; } break;
case 0xD9: {
READ_ADDR();
printf("CMP $%04X,Y\n", addr);
} break;
case 0xDD: {
READ_ADDR();
printf("CMP $%04X,X\n", addr);
} break;
case 0xDE: {
READ_ADDR();
printf("DEC $%04X,X\n", addr);
} break;
case 0xE0: { case 0xE0: {
printf("CPX #$%02X\n", m->memory[m->pc++]); printf("CPX #$%02X\n", m->memory[m->pc++]);
} break; } break;
case 0xE1: {
printf("SBC ($%02X,X)\n", m->memory[m->pc++]);
} break;
case 0xE4: {
printf("CPX $%02X\n", m->memory[m->pc++]);
} break;
case 0xE5: {
printf("SBC $%02X\n", m->memory[m->pc++]);
} break;
case 0xE6: { case 0xE6: {
printf("INC $%02X\n", m->memory[m->pc++]); printf("INC $%02X\n", m->memory[m->pc++]);
} break; } break;
@@ -240,6 +502,14 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
case 0xEA: { case 0xEA: {
printf("NOP\n"); printf("NOP\n");
} break; } break;
case 0xEC: {
READ_ADDR();
printf("CPX $%04X\n", addr);
} break;
case 0xED: {
READ_ADDR();
printf("SBC $%04X\n", addr);
} break;
case 0xEE: { case 0xEE: {
READ_ADDR(); READ_ADDR();
printf("INC $%04X\n", addr); printf("INC $%04X\n", addr);
@@ -248,9 +518,30 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
int8_t offset = m->memory[m->pc++]; int8_t offset = m->memory[m->pc++];
printf("BEQ $%04X\n", m->pc + offset); printf("BEQ $%04X\n", m->pc + offset);
} break; } break;
case 0xF1: {
printf("SBC ($%02X),Y\n", m->memory[m->pc++]);
} break;
case 0xF5: {
printf("SBC $%02X,X\n", m->memory[m->pc++]);
} break;
case 0xF6: {
printf("INC $%02X,X\n", m->memory[m->pc++]);
} break;
case 0xF8: { case 0xF8: {
printf("SED\n"); printf("SED\n");
} break; } break;
case 0xF9: {
READ_ADDR();
printf("SBC $%04X,Y\n", addr);
} break;
case 0xFD: {
READ_ADDR();
printf("SBC $%04X,X\n", addr);
} break;
case 0xFE: {
READ_ADDR();
printf("INC $%04X,X\n", addr);
} break;
default: default:
fprintf(stderr, "unrecognized opcode: %02X\n", op); fprintf(stderr, "unrecognized opcode: %02X\n", op);
exit(1); exit(1);
@@ -261,23 +552,23 @@ void mos6502_disassemble(MOS6502 *m, size_t ins_count) {
void mos6502_free(MOS6502 m) { free(m.memory); } void mos6502_free(MOS6502 m) { free(m.memory); }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc < 3) { if (argc < 2) {
fprintf(stderr, "Usage: %s <path> <ins count>\n", argv[0]); fprintf(stderr, "Usage: %s <path>\n", argv[0]);
return 1; return 1;
} }
MOS6502 m = mos6502_create(); MOS6502 m = mos6502_create();
uint8_t buffer[4000] = {0}; uint8_t buffer[1 << 16] = {0};
FILE *f = fopen(argv[1], "rb"); FILE *f = fopen(argv[1], "rb");
size_t n = fread(buffer, 1, 4000, f); size_t n = fread(buffer, 1, 1 << 16, f);
fclose(f); fclose(f);
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
m.memory[0x600 + i] = buffer[i]; m.memory[0x600 + i] = buffer[i];
} }
mos6502_disassemble(&m, atoi(argv[2])); mos6502_disassemble(&m, n);
mos6502_free(m); mos6502_free(m);
} }