diff --git a/sw/.gitignore b/sw/.gitignore
index 3e1502e129eaed5ec082f67ed43377b86f87602b..ec73f2bb3c2750f223d6c0435f53cd5dcbcd5d40 100644
--- a/sw/.gitignore
+++ b/sw/.gitignore
@@ -3,6 +3,7 @@
 
 # Object files
 *.o
+*.o65
 *.ko
 *.obj
 *.elf
diff --git a/sw/irq.c b/sw/irq.c
index f1baddc0bb486ebf1ae73006d268bf053556b8a2..313ea7d9ca42473676aeae2d642d7cb423ffda34 100644
--- a/sw/irq.c
+++ b/sw/irq.c
@@ -10,7 +10,6 @@ char lastchar;
 
 void handle_irq() {
     uint8_t status;
-    char c;
 
     status = irq_get_status();
 
diff --git a/sw/main.c b/sw/main.c
index 30332d048133507e5d77d973e1e58c01b22ca932..39423a66240c309e9b824175963faec666220407 100644
--- a/sw/main.c
+++ b/sw/main.c
@@ -1,11 +1,13 @@
 #include <stdint.h>
 #include <conio.h>
+#include <string.h>
 
 #include "board_io.h"
 #include "uart.h"
 #include "mapper.h"
 #include "sd_card.h"
 #include "fat.h"
+#include "o65.h"
 
 uint8_t buf[512];
 
@@ -76,6 +78,17 @@ int main() {
 	dos_dentry_t* dos_dentry;
 	uint32_t cluster;
 
+	o65_header_t* header;
+	o65_opt_t* o65_opt;
+	uint8_t* seg_ptr;
+
+	uint8_t* code_base;
+	uint8_t* data_base;
+	uint16_t code_len;
+	uint16_t data_len;
+
+	uint8_t (*exec)(void);
+	uint8_t ret;
 
 	uint16_t reserved_count;
 	uint32_t sectors_per_fat;
@@ -192,14 +205,106 @@ int main() {
 
 	cprintf("DOS name: %.8s.%.3s\n", &dos_dentry->filename, &dos_dentry->extension);
 	
-	cluster = (dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l;
+	cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l;
 	cprintf("Cluster: %ld\n", cluster);
 
 	cprintf("File location: %lx\n", data_region_start + (cluster - 2) * 8);
 
 	sd_readblock(data_region_start + (cluster - 2) * 8);
 
-	cprintf("File contents: %s\n", buf);
+	header = (o65_header_t*)buf;
+
+	if (header->c64_marker == O65_NON_C64 &&
+			header->magic[0] == O65_MAGIC_0 && 
+			header->magic[1] == O65_MAGIC_1 && 
+			header->magic[2] == O65_MAGIC_2) {
+		cprintf("Found a valid o65 file!\n\n");
+
+		cprintf("tbase: %x\n", header->tbase);
+		cprintf("tlen: %x\n", header->tlen);
+		cprintf("dbase: %x\n", header->dbase);
+		cprintf("dlen: %x\n", header->dlen);
+		cprintf("bbase: %x\n", header->bbase);
+		cprintf("blen: %x\n", header->blen);
+		cprintf("zbase: %x\n", header->zbase);
+		cprintf("zlen: %x\n", header->zlen);
+		cprintf("stack: %x\n", header->stack);
+		cprintf("\n");
+
+		code_base = (uint8_t*)header->tbase;
+		data_base = (uint8_t*)header->dbase;
+		code_len = header->tlen;
+		data_len = header->dlen;
+
+
+		o65_opt = (o65_opt_t*)(buf + sizeof(o65_header_t));
+		while (o65_opt->olen)
+		{
+			cprintf("Option Length: %d\n", o65_opt->olen);
+			cprintf("Option Type: %x ", o65_opt->type);
+			switch (o65_opt->type) {
+				case O65_OPT_FILENAME: cprintf("Filename\n"); break;
+				case O65_OPT_OS: cprintf("OS\n"); break;
+				case O65_OPT_ASSEMBLER: cprintf("Assembler\n"); break;
+				case O65_OPT_AUTHOR: cprintf("Author\n"); break;
+				case O65_OPT_DATE: cprintf("Creation Date\n"); break;
+				default: cprintf("Invalid\n"); break;
+			}
+
+			if (o65_opt->type != O65_OPT_OS) {
+				for (i = 0; i < o65_opt->olen - 2; i++) {
+					cprintf("%c", o65_opt->data[i]);
+				}
+			} else {
+				cprintf("%x", o65_opt->data[0]);
+			}
+			cprintf("\n\n");
+			o65_opt = (o65_opt_t*)((uint8_t*)o65_opt + o65_opt->olen);
+		}
+
+		seg_ptr = (uint8_t*)o65_opt + 1;
+
+		cprintf("Code: \n");
+		for (i = 0; i < code_len; i++) {
+			cprintf("%x ", seg_ptr[i]);
+		}
+		cprintf("\n\n");
+
+		memcpy((uint8_t*)code_base, seg_ptr, code_len);
+
+		seg_ptr+=code_len;
+
+		cprintf("Data: \n");
+		for (i = 0; i < data_len; i++) {
+			cprintf("%x ", seg_ptr[i]);
+		}
+		cprintf("\n\n");
+
+		memcpy((uint8_t*)data_base, seg_ptr, data_len);
+
+		cprintf("Memory Copied!\n");
+		cprintf("Code: \n");
+		for (i = 0; i < code_len; i++) {
+			cprintf("%x ", code_base[i]);
+		}
+		cprintf("\n\n");
+		cprintf("Data: \n");
+		for (i = 0; i < data_len; i++) {
+			cprintf("%x ", data_base[i]);
+		}
+		cprintf("\n\n");
+
+		exec = (uint8_t (*)(void))code_base;
+
+		ret = 0;
+
+		ret = (*exec)();
+
+		cprintf("ret: %x\n", ret);
+
+
+	}
+
 
 	cprintf("Done!\n");
 
diff --git a/sw/o65.h b/sw/o65.h
new file mode 100644
index 0000000000000000000000000000000000000000..1871ec91f20817fa3181e46a2650808a311b1a09
--- /dev/null
+++ b/sw/o65.h
@@ -0,0 +1,65 @@
+#ifndef _O65_H
+#define _O65_H
+
+#include <stdint.h>
+
+#define O65_NON_C64 0x0001
+#define O65_MAGIC_0 0x6f
+#define O65_MAGIC_1 0x36
+#define O65_MAGIC_2 0x35
+
+#define O65_OPT_FILENAME 0
+#define O65_OPT_OS 1
+#define O65_OPT_ASSEMBLER 2
+#define O65_OPT_AUTHOR 3
+#define O65_OPT_DATE 4
+
+#define O65_OS_OSA65 1
+#define O65_OS_LUNIX 2
+#define O65_OS_CC65 3
+#define O65_OS_OPENCBM 4
+#define O65_OS_SUPER6502 5
+
+typedef union {
+    struct {
+        int cpu : 1;
+        int reloc : 1;
+        int size : 1;
+        int obj : 1;
+        int simple : 1;
+        int chain : 1;
+        int bsszero : 1;
+        int cpu2 : 4;
+        int align : 2;
+    };
+    uint16_t _mode;
+} o65_mode_t;
+
+typedef struct {
+    uint16_t c64_marker;
+    uint8_t magic[3];
+    uint8_t version;
+
+    o65_mode_t mode;
+
+    uint16_t tbase;
+    uint16_t tlen;
+    uint16_t dbase;
+    uint16_t dlen;
+    uint16_t bbase;
+    uint16_t blen;
+    uint16_t zbase;
+    uint16_t zlen;
+    uint16_t stack;
+
+} o65_header_t;
+
+typedef struct {
+    uint8_t olen;
+    uint8_t type;
+    uint8_t data[1];    //This is actually variable length
+} o65_opt_t;
+
+#endif
+
+
diff --git a/sw/test_exec/Makefile b/sw/test_exec/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..cfcfe6d37a9a1ba1f7dc18478f5c20e318de0952
--- /dev/null
+++ b/sw/test_exec/Makefile
@@ -0,0 +1,41 @@
+CC=cl65
+CFLAGS=-T -t none -I. --cpu "65C02"
+test: CFLAGS=-T -t sim65c02 -I.
+LDFLAGS=-C link.ld -m $(NAME).map
+SIM=sim65
+SIMARGS=-v -c -x 1000000
+
+NAME=test
+
+BIN=$(NAME).o65
+HEX=$(NAME).hex
+
+LISTS=lists
+
+SRCS=$(wildcard *.s) $(wildcard *.c)
+OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
+OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
+
+all: $(BIN)
+
+$(HEX): $(BIN)
+	objcopy --input-target=binary --output-target=ihex $(BIN) $(HEX)
+	
+
+$(BIN): $(OBJS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+%.o: %.c $(LISTS)
+	$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
+
+%.o: %.s $(LISTS)
+	$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
+
+$(LISTS):
+	mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
+
+.PHONY: clean
+clean:
+	rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map
+	rm -rf $(TEST_OBJS) $(TEST_BIN)
+
diff --git a/sw/test_exec/link.ld b/sw/test_exec/link.ld
new file mode 100644
index 0000000000000000000000000000000000000000..ade4e99ac06c63a24c5da88e15c44016cc41f7f1
--- /dev/null
+++ b/sw/test_exec/link.ld
@@ -0,0 +1,43 @@
+MEMORY
+{
+  ZP:  start = $0,    size = $100,  type = rw, define = yes;
+  SDRAM: start = $1000, size = $6ef0, type = rw, define = yes;
+}
+
+FILES {
+    %O: format = o65;
+}
+
+SEGMENTS {
+    ZEROPAGE: load = ZP,  type = zp,  define   = yes;
+    DATA:     load = SDRAM, type = rw,  define   = yes, run = SDRAM;
+    BSS:      load = SDRAM, type = bss, define   = yes;
+    HEAP:     load = SDRAM, type = bss, optional = yes;
+    STARTUP:  load = SDRAM, type = ro;
+    ONCE:     load = SDRAM, type = ro,  optional = yes;
+    CODE:     load = SDRAM, type = ro;
+    RODATA:   load = SDRAM, type = ro;
+}
+
+FEATURES {
+    CONDES:    segment = STARTUP,
+               type    = constructor,
+               label   = __CONSTRUCTOR_TABLE__,
+               count   = __CONSTRUCTOR_COUNT__;
+    CONDES:    segment = STARTUP,
+               type    = destructor,
+               label   = __DESTRUCTOR_TABLE__,
+               count   = __DESTRUCTOR_COUNT__;
+}
+
+SYMBOLS {
+    # Define the stack size for the application
+    __STACKSIZE__:  value = $0200, type = weak;
+    __STACKSTART__: type = weak, value = $0800; # 2k stack
+
+}
+
+FORMATS {
+        o65: os = 5, version = 0, type = small,
+             export = _main;
+    }
diff --git a/sw/test_exec/main.c b/sw/test_exec/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..ad40be35a6eacf99b0ca7f3bb26f4349c4d1ef5f
--- /dev/null
+++ b/sw/test_exec/main.c
@@ -0,0 +1,3 @@
+int main() {
+    return 0x41;
+}
\ No newline at end of file