Add start of emulator, debugger
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8c4167f..a913e68 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,4 +12,4 @@
 		WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
 endif()
 
-add_executable(emu-6502 main.c cpu.c cpu.h instructions.h)
+add_executable(emu-6502 main.c cpu.c cpu.h dbg.c dbg.h instructions.h)
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);
diff --git a/cpu.h b/cpu.h
index 20551ec..651f97f 100644
--- a/cpu.h
+++ b/cpu.h
@@ -1,10 +1,13 @@
 #pragma once
 
 #include <stdint.h>
+#include <stdbool.h>
+
+#define REGISTERS R(A) R(X) R(Y) R(SP)
 
 enum // Registers
 {
-	A, X, Y, SR, SP
+	A, X, Y, SP
 };
 
 enum // Flags
@@ -101,12 +104,27 @@
 	FETCH_NO_INDIRECTION = 1, // Do not follow indirection (used for disassembly)
 };
 
+// Status register
+typedef struct __attribute__((packed))
+{
+	bool negative	: 1;
+	bool overflow	: 1;
+	bool unused		: 1;
+	bool break_		: 1;
+	bool decimal	: 1;
+	bool no_int		: 1;
+	bool zero		: 1;
+	bool carry		: 1;
+} status_t;
+
 // Emulator instance, create with new_cpu()
 typedef struct
 {
-	uint8_t regs[5]; // A, X, Y, SP and SR registers
+	uint8_t regs[4]; // A, X, Y, SP registers
 	uint16_t pc;
+	status_t status;
 	uint8_t *mem;
+	bool running;
 } cpu_t;
 
 // Argument type, includes both pointer and its value
@@ -117,6 +135,7 @@
 } arg_t;
 
 cpu_t new_cpu();
+void step(cpu_t *cpu);
 void free_cpu(cpu_t *cpu);
 void die(const char *message);
 void disas(cpu_t *cpu);
diff --git a/dbg.c b/dbg.c
new file mode 100644
index 0000000..bdc2b31
--- /dev/null
+++ b/dbg.c
@@ -0,0 +1,52 @@
+#include "dbg.h"
+#include "cpu.h"
+
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <string.h>
+#include <stdlib.h>
+
+void debug(cpu_t *cpu)
+{
+	while (true)
+	{
+		char *input = readline("\033[33m> \033[0m");
+		if (!input)
+			continue;
+
+		char *tok = strtok(input, " \t\r\n\v");
+		
+		if (!strcmp(tok, "step") || !strcmp(tok, "s"))
+		{
+			step(cpu);
+		}
+		else if (!strcmp(tok, "show") || !strcmp(tok, "print"))
+		{
+			if ((tok = strtok(NULL, " ")))
+			{
+				char *ok = 0;
+				if (tok[0] == '$')
+				{
+					uint16_t addr = strtol(tok + 1, &ok, 16);
+
+					if (ok == 0)
+					{
+						printf("Memory:\n");
+						printf("\t$%x	%x\n", addr, cpu->mem[addr]);
+						printf("\t$%x	%x\n", addr + 1, cpu->mem[addr + 1]);
+					}
+				}
+				else
+				{
+					printf("Registers:\n");
+
+					#define R(r) printf("\t" #r ":	%x\n", cpu->regs[r]);
+						REGISTERS
+					#undef R
+				}
+			}
+		}
+
+		add_history(input);
+	}
+}
diff --git a/dbg.h b/dbg.h
new file mode 100644
index 0000000..c31c1c3
--- /dev/null
+++ b/dbg.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "cpu.h"
+
+void debug(cpu_t *cpu);
diff --git a/test.dat b/test.dat
index 0d6ba15..d5569e0 100644
--- a/test.dat
+++ b/test.dat
Binary files differ