Add start of emulator, debugger
diff --git a/cpu.c b/cpu.c
index af9ad27..fe5cf6a 100644
--- a/cpu.c
+++ b/cpu.c
@@ -7,15 +7,18 @@
 #include <string.h>
 
 #define die(m, ...) \
-	printf("\033[31mError: " m "\033[0m\n", ##__VA_ARGS__); \
+	printf("\033[31m" m "\033[0m\n", ##__VA_ARGS__); \
 	exit(1);
 
+#define warn(m, ...) \
+	printf("\033[33m" m "\033[0m\n", ##__VA_ARGS__);
+
 cpu_t new_cpu()
 {
 	cpu_t cpu = { 0 };
-	cpu.regs[SR] = UNUSED; // unused flag always set
 	cpu.regs[SP] = 0xFD; // stack at is 0x100 + SP
 	cpu.pc = 0; // arbitrary program counter start
+	cpu.running = true;
 	cpu.mem = malloc(0xFFFF);
 	memset(cpu.mem, 0, 0xFFFF);
 
@@ -27,24 +30,117 @@
 	return cpu;
 }
 
+void stack_push(cpu_t *cpu, uint8_t v)
+{
+	cpu->mem[cpu->regs[SP]-- + 0x100] = v;
+}
+
+uint8_t stack_pop(cpu_t *cpu)
+{
+	return cpu->mem[cpu->regs[SP]++ + 0x100];
+}
+
 void free_cpu(cpu_t *cpu)
 {
 	free(cpu->mem);
 }
 
-void execute(cpu_t *cpu, const char *mnemonic, uint8_t op, arg_t addr)
+void stat_nz(cpu_t *cpu, int8_t v)
 {
+	cpu->status.negative = v < 0;
+	cpu->status.zero = v == 0;
+}
+
+// Used to check for overflow, is c unique?
+bool last_unique(bool a, bool b, bool c)
+{
+	return a == b && a != c;
+}
+
+void stat_cv(cpu_t *cpu, uint8_t a, uint8_t b, uint8_t c)
+{
+	cpu->status.overflow = last_unique(a >> 7, b >> 7, c >> 7);
+	cpu->status.carry = c < a || c < b;
+}
+
+void execute(cpu_t *cpu, const char *mnemonic, uint8_t op, arg_t a)
+{
+	// used to save space
+	#define REGS \
+		R(X) R(A) R(Y)
+
 	switch (op) {
-		
+		// Load and store instructions:
+		#define R(reg) \
+			case LD##reg: \
+				cpu->regs[reg] = a.val; \
+				stat_nz(cpu, a.val); \
+				break;
+
+			REGS
+
+		#undef R
+
+		#define R(reg) \
+			case ST##reg: \
+				cpu->mem[a.ptr] = cpu->regs[reg]; \
+				break; \
+
+			REGS
+
+		#undef R
+
+		// Arithmetic instructions:
+		// NOTE: binary coded decimals are NOT SUPPORTED because I don't want
+		// to implement them.
+		case ADC:
+		{
+			uint8_t sum = cpu->regs[A] + a.val + cpu->status.carry;
+			// signed overflow
+			stat_cv(cpu, cpu->regs[A], a.val + cpu->status.carry, sum);
+			stat_nz(cpu, sum);
+			cpu->regs[A] = sum;
+			break;
+		}
+
+		case SBC:
+		{
+			uint8_t diff = cpu->regs[A] - a.val - !cpu->status.carry;
+			stat_cv(cpu, cpu->regs[A], a.val - !cpu->status.carry, diff);
+			stat_nz(cpu, diff);
+			cpu->regs[A] = diff;
+			break;
+		}
+
+		case INC:
+			cpu->mem[a.ptr]++;
+			stat_nz(cpu, cpu->mem[a.ptr]);
+			break;
+
+		case INX:
+			cpu->regs[X]++;
+			stat_nz(cpu, cpu->regs[X]);
+			break;
+
+		case INY:
+			cpu->regs[Y]++;
+			stat_nz(cpu, cpu->regs[Y]);
+			break;
+
+		case DEC:
+			cpu->mem[a.ptr]--;
+			stat_nz(cpu, cpu->mem[a.ptr]);
+			break;
 	}
+	#undef REGS
 }
 
 uint16_t le_to_native(uint8_t a, uint8_t b)
 {
 #ifdef LITTLE_ENDIAN
-	return a << 8 | b;
-#else
 	return b << 8 | a;
+#else
+	return a << 8 | b;
 #endif
 }
 
@@ -91,15 +187,21 @@
 
 		case AM_REL:
 		{
-			// PC should point to the opcode
-			// braces needed to avoid c stupidity
-			uint16_t pc = cpu->pc - 1;
-			return arg_ptr(cpu, f, cpu->mem[cpu->pc++] + pc);
+			// Aparently, PC should will point to the NEXT opcode
+			// I can't find any documentation on this unfortunately, but
+			// I have discovered this through testing the output of other
+			// assemblers.
+			uint16_t pc = cpu->pc + 1;
+			return arg_ptr(cpu, f, (int8_t)cpu->mem[cpu->pc++] + pc);
 		}
 
 		case AM_IND:
 		{
 			uint16_t addr = fetch_le(cpu);
+
+			if (f & FETCH_NO_INDIRECTION)
+				return arg_imm(addr);
+
 			uint8_t low = cpu->mem[addr],
 				high = cpu->mem[addr + 1];
 
@@ -121,6 +223,10 @@
 		case AM_ZIX:
 		{
 			uint8_t zp = cpu->mem[cpu->pc++];
+
+			if (f & FETCH_NO_INDIRECTION)
+				return arg_imm(zp);
+
 			uint16_t addr = zp + cpu->regs[X];
 			uint16_t indirect = le_to_native(cpu->mem[addr], cpu->mem[addr + 1]);
 			return arg_ptr(cpu, f, indirect);
@@ -129,6 +235,10 @@
 		case AM_ZIY:
 		{
 			uint8_t zp = cpu->mem[cpu->pc++];
+
+			if (f & FETCH_NO_INDIRECTION)
+				return arg_imm(zp);
+
 			uint16_t base = le_to_native(cpu->mem[zp], cpu->mem[zp + 1]);
 			return arg_ptr(cpu, f, base + cpu->regs[Y]);
 		}
@@ -199,7 +309,7 @@
 
 void disas_step(cpu_t *cpu)
 {
-	printf("%x", cpu->pc);
+	printf("$%x", cpu->pc);
 	uint8_t op = cpu->mem[cpu->pc++];
 	switch (op)
 	{
@@ -214,12 +324,13 @@
 #undef INST
 
 		default:
-			die("Undefined opcode %x", op);
+			warn("\tUndefined opcode %x", op);
 	}
 }
 
 void disas(cpu_t *cpu)
 {
+	// Raw binary, no way to know what's code what isn't
 	while (cpu->pc < 0xFFFF)
 	{
 		disas_step(cpu);