#include "duffle.amd64.win32.h"

// --- Semantic Tags (Using X-Macros & Enum_) ---
#define Tag_Entries() \
		X(Define,  "Define",  0x0018AEFF, ":") \
		X(Call,    "Call",    0x00D6A454, "~") \
		X(Data,    "Data",    0x0094BAA1, "$") \
		X(Imm,     "Imm",     0x004AA4C2, "^") \
		X(Comment, "Comment", 0x00AAAAAA, ".") \
		X(Format,  "Format",  0x003A2F3B, " ") \
		X(Lambda,  "Lambda",  0x00D675A4, "%") 

typedef Enum_(U4, STag) {
#define X(n, s, c, p) tmpl(STag, n),
		Tag_Entries()
#undef X
		STag_Count,
};
global U4 tag_colors[] = {
#define X(n, s, c, p) c,
		Tag_Entries()
#undef X
};
global const char* tag_prefixes[] = {
#define X(n, s, c, p) p,
		Tag_Entries()
#undef X
};
global const char* tag_names[] = {
#define X(n, s, c, p) s,
		Tag_Entries()
#undef X
};

#define pack_token(tag, val) ((u4_(tag) << 28) | (u4_(val) & 0x0FFFFFFF))
#define unpack_tag(token)    ( ((token) >> 28) & 0x0F)
#define unpack_val(token)    (  (token)        & 0x0FFFFFFF)

#define TOKENS_PER_ROW 8

#define MODE_NAV  0
#define MODE_EDIT 1

global FArena tape_arena;
global FArena anno_arena;
global U8     cursor_idx  = 0;
global U4     editor_mode = MODE_NAV;
global B4     mode_switch_now = false;

global FArena code_arena;

global U8 vm_rax         = 0; 
global U8 vm_rdx         = 0; 
global U8 vm_globals[16] = {0};

global B4 run_full       = false;
global U8 log_buffer[16] = {0};
global U4 log_count      = 0;
global S4 scroll_y_offset = 0;

// New GDI log
#define GDI_LOG_MAX_LINES 10
#define GDI_LOG_MAX_LINE_LEN 128
global char gdi_log_buffer[GDI_LOG_MAX_LINES][GDI_LOG_MAX_LINE_LEN] = {0};
global U4 gdi_log_count = 0;

internal void debug_log(Str8 fmt, KTL_Str8 table) {
		// A static buffer for our log lines.
		LP_ UTF8 console_log_buffer[1024];
		mem_zero(u8_(console_log_buffer), 1024);

		// Format the string.
		Str8 result = str8_fmt_ktl_buf(slice_ut_arr(console_log_buffer), table, fmt);

		// Also write to our GDI log buffer
		if (gdi_log_count < GDI_LOG_MAX_LINES) {
				U4 len_to_copy = result.len < GDI_LOG_MAX_LINE_LEN - 1 ? result.len : GDI_LOG_MAX_LINE_LEN - 1;
				mem_copy(u8_(gdi_log_buffer[gdi_log_count]), u8_(result.ptr), len_to_copy);
				gdi_log_buffer[gdi_log_count][len_to_copy] = '\0';
				gdi_log_count++;
		}

		// Get stdout handle.
		MS_Handle stdout_handle = ms_get_std_handle(MS_STD_OUTPUT);

		// Write the formatted string.
		ms_write_console(stdout_handle, result.ptr, (U4)result.len, nullptr, 0);

		// Write a newline.
		ms_write_console(stdout_handle, (UTF8 const*r)"\n", 1, nullptr, 0);
}

U8 ms_builtin_print(U8 val, U8 rdx_val, U8 r8_val, U8 r9_val) {
		char hex1[9], hex2[9], hex3[9], hex4[9];
		u64_to_hex(val, hex1, 8); hex1[8] = '\0';
		u64_to_hex(rdx_val, hex2, 8); hex2[8] = '\0';
		u64_to_hex(r8_val, hex3, 8); hex3[8] = '\0';
		u64_to_hex(r9_val, hex4, 8); hex4[8] = '\0';
		
		KTL_Slot_Str8 log_table[] = {
				{ ktl_str8_key("v1"), str8(hex1) },
				{ ktl_str8_key("v2"), str8(hex2) },
				{ ktl_str8_key("v3"), str8(hex3) },
				{ ktl_str8_key("v4"), str8(hex4) },
		};
		debug_log(str8("FFI PRINT -> RCX:<v1> RDX:<v2> R8:<v3> R9:<v4>"), ktl_str8_from_arr(log_table));
	if (log_count < 16) log_buffer[log_count++] = val;
		return val;
}

// Visual Linker & O(1) Dictionary
global U4 tape_to_code_offset[65536] = {0};

// --- WinAPI Persistence ---
#define MS_GENERIC_READ          0x80000000
#define MS_GENERIC_WRITE         0x40000000
#define MS_CREATE_ALWAYS         2
#define MS_OPEN_EXISTING         3
#define MS_FILE_ATTRIBUTE_NORMAL 0x80
#define MS_VK_F1                 0x70
#define MS_VK_F2                 0x71

WinAPI void* ms_create_file_a(char const* lpFileName, U4 dwDesiredAccess, U4 dwShareMode, void* lpSecurityAttributes, U4 dwCreationDisposition, U4 dwFlagsAndAttributes, void* hTemplateFile) asm("CreateFileA");
WinAPI B4    ms_write_file(void* hFile, void const* lpBuffer, U4 nNumberOfBytesToWrite, U4* lpNumberOfBytesWritten, void* lpOverlapped) asm("WriteFile");
WinAPI B4    ms_read_file(void* hFile, void* lpBuffer, U4 nNumberOfBytesToRead, U4* lpNumberOfBytesRead, void* lpOverlapped) asm("ReadFile");
WinAPI B4    ms_close_handle(void* hObject) asm("CloseHandle");

#define PRIM_SWAP    1
#define PRIM_MULT    2
#define PRIM_ADD     3
#define PRIM_FETCH   4
#define PRIM_DEC     5
#define PRIM_STORE   6
#define PRIM_RET_Z   7
#define PRIM_RET     8
#define PRIM_PRINT   9
#define PRIM_RET_S   10
#define PRIM_DUP     11
#define PRIM_DROP    12
#define PRIM_SUB     13
#define PRIM_EXECUTE 14
#define PRIM_IF      15
#define PRIM_END     16
#define PRIM_RECURSE 17

global const char* prim_names[] = {
	"", 
	"SWAP    ", 
	"MULT    ", 
	"ADD     ", 
	"FETCH   ", 
	"DEC     ", 
	"STORE   ", 
	"RET_IF_Z", 
	"RETURN  ", 
	"PRINT   ",
	"RET_IF_S",
	"DUP     ",
	"DROP    ",
	"SUB     ",
	"EXECUTE ",
	"[       ",
	"]       ",
	"RECURSE "
};

internal U4 resolve_name_to_index(const char* ref_name);
internal void relink_tape(void);

IA_ void compile_and_run_tape(void);

internal void save_cartridge(void) {
		void* hFile = ms_create_file_a("cartridge.bin", MS_GENERIC_WRITE, 0, nullptr, MS_CREATE_ALWAYS, MS_FILE_ATTRIBUTE_NORMAL, nullptr);
		if (hFile != (void*)-1) {
				U4 written = 0;
				ms_write_file(hFile, & tape_arena.used, 8, & written, nullptr);
				ms_write_file(hFile, & anno_arena.used, 8, & written, nullptr);
				ms_write_file(hFile, & cursor_idx,      8, & written, nullptr);
				ms_write_file(hFile, (void*)tape_arena.start, (U4)tape_arena.used, & written, nullptr);
				ms_write_file(hFile, (void*)anno_arena.start, (U4)anno_arena.used, & written, nullptr);
				ms_close_handle(hFile);
		}
}

internal void load_cartridge(void) {
		void* hFile = ms_create_file_a("cartridge.bin", MS_GENERIC_READ, 0, nullptr, MS_OPEN_EXISTING, MS_FILE_ATTRIBUTE_NORMAL, nullptr);
		if (hFile != (void*)-1) {
				U4 read = 0;
				ms_read_file(hFile, & tape_arena.used, 8, & read, nullptr);
				ms_read_file(hFile, & anno_arena.used, 8, & read, nullptr);
				ms_read_file(hFile, & cursor_idx,      8, & read, nullptr);
				ms_read_file(hFile, (void*)tape_arena.start, (U4)tape_arena.used, & read, nullptr);
				ms_read_file(hFile, (void*)anno_arena.start, (U4)anno_arena.used, & read, nullptr);
				ms_close_handle(hFile);
				relink_tape();
				compile_and_run_tape();
		}
}

IA_ void scatter(U4 token, const char* anno_str) { 
	if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) {
				U4 tag = unpack_tag(token);
				U4 val = unpack_val(token);

		if (anno_str && (tag == STag_Call || tag == STag_Imm)) {
						val = resolve_name_to_index(anno_str);
				}

		U4*r ptr = u4_r(tape_arena.start + tape_arena.used);
		ptr[0]           = pack_token(tag, val);
		tape_arena.used += sizeof(U4);
		U8*r aptr = u8_r(anno_arena.start + anno_arena.used);
		aptr[0] = 0;
		if (anno_str) {
			char* dest = (char*)aptr;
			int i = 0; while(i < 8 && anno_str[i]) { dest[i] = anno_str[i]; i ++; }
		}
		anno_arena.used += sizeof(U8);
	}
}

internal void emit8(U1 b) { 
	if (code_arena.used + 1 <= code_arena.capacity) {
		u1_r(code_arena.start + code_arena.used)[0] = b;
		code_arena.used += 1;
	}
}
internal void emit32(U4 val) { 
	if (code_arena.used + 4 <= code_arena.capacity) {
		u4_r(code_arena.start + code_arena.used)[0] = val;
		code_arena.used += 4;
	}
}
internal void emit64(U8 val) {
	if (code_arena.used + 8 <= code_arena.capacity) {
		u8_r(code_arena.start+ code_arena.used)[0] = val;
		code_arena.used += 8;
	}
}

internal void pad32(void) {
	while ((code_arena.used % 4) != 0) emit8(0x90);
}

internal U4 resolve_name_to_index(const char* ref_name) {
		U8 tape_count = tape_arena.used / sizeof(U4);
		U4*r tape_ptr = u4_r(tape_arena.start);
		U8*r anno_ptr = u8_r(anno_arena.start);

		U8 prim_count = array_len(prim_names);
		for (int p = 1; p < prim_count; p++) {
				int match = 1;
				for (int c = 0; c < 8; c++) {
						char c1 = ref_name[c] ? ref_name[c] : ' ';
						char c2 = prim_names[p][c] ? prim_names[p][c] : ' ';
						if (c1 != c2) { match = 0; break; }
				}
				if (match) return p + 0x10000;
		}

		for (U8 j = 0; j < tape_count; j++) {
				if (unpack_tag(tape_ptr[j]) == STag_Define) {
						char* def_name = (char*)&anno_ptr[j];
						int match = 1;
						for (int c = 0; c < 8; c++) {
								char c1 = ref_name[c] ? ref_name[c] : ' ';
								char c2 = def_name[c] ? def_name[c] : ' ';
								if (c1 != c2) { match = 0; break; }
						}
						if (match) return j;
				}
		}
		return 0;
}

internal void relink_tape(void) {
	U8 tape_count = tape_arena.used / sizeof(U4);
	U4*r tape_ptr = u4_r(tape_arena.start);
	U8*r anno_ptr = u8_r(anno_arena.start);

	for (U8 i = 0; i < tape_count; i++) {
		U4 t = tape_ptr[i];
		U4 tag = unpack_tag(t);
		if (tag == STag_Call || tag == STag_Imm) {
			char* ref_name = (char*)&anno_ptr[i];
						U4 new_val = resolve_name_to_index(ref_name);
			tape_ptr[i] = pack_token(tag, new_val);
		}
	}
}

#pragma region x64 Emission DSL
// ===================================================================================================================
// x64 Emission DSL
// Follows the same bit-field composition pattern as the GP command macros.
// ===================================================================================================================

// --- REX Prefix Composition ---
// REX byte: 0100 W R X B
// W = 64-bit operand width
// R = extends ModRM.reg   field to reach R8-R15
// X = extends SIB.index   field to reach R8-R15
// B = extends ModRM.r/m   field to reach R8-R15
#define x64_rex_offset_W 3
#define x64_rex_offset_R 2
#define x64_rex_offset_X 1
#define x64_rex_offset_B 0

#define x64_rex_base 0x40
#define x64_rex_W    (0x1 << x64_rex_offset_W) // 64-bit operand size
#define x64_rex_R    (0x1 << x64_rex_offset_R) // Extend reg  field
#define x64_rex_X    (0x1 << x64_rex_offset_X) // Extend index field
#define x64_rex_B    (0x1 << x64_rex_offset_B) // Extend r/m  field

#define x64_rex(flags)  (x64_rex_base | (flags))
#define x64_REX         x64_rex(x64_rex_W)                    // 0x48 - 64-bit, standard regs
#define x64_REX_R       x64_rex(x64_rex_W | x64_rex_R)        // 0x4C - 64-bit, extended reg field
#define x64_REX_B       x64_rex(x64_rex_W | x64_rex_B)        // 0x49 - 64-bit, extended r/m  field
#define x64_REX_RB      x64_rex(x64_rex_W | x64_rex_R | x64_rex_B) // 0x4D

// --- Register Encoding ---
// These are the 3-bit register IDs used in ModRM and SIB fields.
#define x64_reg_RAX 0x0 // 000
#define x64_reg_RCX 0x1 // 001
#define x64_reg_RDX 0x2 // 010
#define x64_reg_RBX 0x3 // 011
#define x64_reg_RSP 0x4 // 100 (also: SIB follows when in r/m with Mod != 11)
#define x64_reg_RBP 0x5 // 101 (also: disp32 no base when Mod = 00)
#define x64_reg_RSI 0x6 // 110
#define x64_reg_RDI 0x7 // 111
// Extended registers (require REX.R or REX.B)
#define x64_reg_R8  0x0 // 000 + REX.R/B
#define x64_reg_R9  0x1 // 001 + REX.R/B
#define x64_reg_R10 0x2 // 010 + REX.R/B
#define x64_reg_R11 0x3 // 011 + REX.R/B

// --- ModRM Composition ---
// ModRM byte: [Mod:2][Reg:3][R/M:3]
// Mod=11 -> both operands are registers (no memory)
// Mod=00 -> r/m is a memory address, no displacement
// Mod=01 -> r/m is a memory address + 8-bit displacement
// Mod=10 -> r/m is a memory address + 32-bit displacement
#define x64_mod_mem        0x0 // 00 - memory, no displacement
#define x64_mod_mem_disp8  0x1 // 01 - memory + 8-bit displacement
#define x64_mod_mem_disp32 0x2 // 10 - memory + 32-bit displacement
#define x64_mod_reg        0x3 // 11 - register direct (no memory)

#define x64_modrm_offset_mod 6
#define x64_modrm_offset_reg 3
#define x64_modrm_offset_rm  0

#define x64_modrm(mod, reg, rm) \
		(((mod) << x64_modrm_offset_mod) | ((reg) << x64_modrm_offset_reg) | ((rm) << x64_modrm_offset_rm))

// Register-to-register ModRM shortcuts (Mod=11, the common case)
#define x64_modrm_rr(reg, rm)       x64_modrm(x64_mod_reg, reg, rm)

// Commonly used ModRM bytes in this runtime (reg direct)
#define x64_modrm_RAX_RAX  x64_modrm_rr(x64_reg_RAX, x64_reg_RAX) // 0xC0
#define x64_modrm_RAX_RCX  x64_modrm_rr(x64_reg_RAX, x64_reg_RCX) // 0xC1
#define x64_modrm_RAX_RDX  x64_modrm_rr(x64_reg_RAX, x64_reg_RDX) // 0xC2
#define x64_modrm_RAX_RBX  x64_modrm_rr(x64_reg_RAX, x64_reg_RBX) // 0xC3
#define x64_modrm_RCX_RAX  x64_modrm_rr(x64_reg_RCX, x64_reg_RAX) // 0xC8
#define x64_modrm_RCX_RBX  x64_modrm_rr(x64_reg_RCX, x64_reg_RBX) // 0xCB
#define x64_modrm_RDX_RAX  x64_modrm_rr(x64_reg_RDX, x64_reg_RAX) // 0xD0

// Memory + disp8 ModRM shortcuts (Mod=01)
#define x64_modrm_RAX_mem_disp8_RBX  x64_modrm(x64_mod_mem_disp8, x64_reg_RAX, x64_reg_RBX) // 0x43
#define x64_modrm_RDX_mem_disp8_RBX  x64_modrm(x64_mod_mem_disp8, x64_reg_RDX, x64_reg_RBX) // 0x53

// SIB-addressed ModRM (Mod=00, R/M=RSP signals SIB follows)
#define x64_modrm_RAX_sib  x64_modrm(x64_mod_mem, x64_reg_RAX, x64_reg_RSP) // 0x04
#define x64_modrm_RDX_sib  x64_modrm(x64_mod_mem, x64_reg_RDX, x64_reg_RSP) // 0x14

// --- SIB Composition ---
// SIB byte: [Scale:2][Index:3][Base:3]
// Scale: 00=*1, 01=*2, 10=*4, 11=*8
#define x64_sib_scale_1 0x0 // 00
#define x64_sib_scale_2 0x1 // 01
#define x64_sib_scale_4 0x2 // 10
#define x64_sib_scale_8 0x3 // 11

#define x64_sib_offset_scale 6
#define x64_sib_offset_index 3
#define x64_sib_offset_base  0

#define x64_sib(scale, index, base) \
		(((scale) << x64_sib_offset_scale) | ((index) << x64_sib_offset_index) | ((base) << x64_sib_offset_base))

// Tape drive SIB: [rbx + rax*8]
// Scale=8, Index=RAX, Base=RBX
#define x64_sib_tape  x64_sib(x64_sib_scale_8, x64_reg_RAX, x64_reg_RBX) // 0xC3

// --- Opcodes ---
#define x64_op_MOV_rm_reg   0x89 // mov r/m, reg  (store: reg -> memory or register)
#define x64_op_MOV_reg_rm   0x8B // mov reg, r/m  (load:  memory or register -> reg)
#define x64_op_MOV_rm_imm32 0xC7 // mov r/m, imm32 (sign-extended to 64-bit)
#define x64_op_MOV_rax_imm64 0xB8 // mov rax, imm64 (register baked into opcode)
#define x64_op_MOV_r10_imm64 0xBA // mov r10, imm64 (B8 + r10_id=2, needs REX.B)

#define x64_op_XCHG_rm_reg  0x87 // xchg r/m, reg
#define x64_op_ADD_rm_reg   0x01 // add r/m, reg
#define x64_op_SUB_rm_reg   0x29 // sub r/m, reg
#define x64_op_IMUL_reg_rm  0x0F // imul prefix (followed by 0xAF)
#define x64_op_IMUL_reg_rm2 0xAF // imul reg, r/m (second byte)
#define x64_op_TEST_rm_reg  0x85 // test r/m, reg (sets ZF and SF)
#define x64_op_UNARY        0xFF // inc/dec/call-indirect (Reg field = opcode extension)
#define x64_op_ARITH_imm8   0x83 // add/sub/etc with sign-extended 8-bit immediate (Reg = extension)
#define x64_op_ARITH_imm32  0x81 // add/sub/etc with 32-bit immediate (Reg = extension)

// Opcode extensions (used as the Reg field of ModRM with 0xFF and 0x83)
#define x64_ext_INC   0x0 // /0
#define x64_ext_DEC   0x1 // /1
#define x64_ext_CALL  0x2 // /2  (used with 0xFF for indirect call)
#define x64_ext_ADD   0x0 // /0  (used with 0x83/0x81)
#define x64_ext_SUB   0x5 // /5  (used with 0x83/0x81)

#define x64_op_CALL_rel32   0xE8 // call rel32
#define x64_op_JMP_rel32    0xE9 // jmp  rel32
#define x64_op_JNZ_rel8     0x75 // jnz  rel8  (jump if Zero Flag not set)
#define x64_op_JNS_rel8     0x79 // jns  rel8  (jump if Sign Flag not set)
#define x64_op_RET          0xC3 // ret
#define x64_op_NOP          0x90 // nop (used for padding to 32-bit alignment)

// Push/Pop (opcode encodes register directly, no ModRM)
#define x64_op_PUSH_RBX 0x53 // push rbx  (50 + rbx_id=3)
#define x64_op_POP_RBX  0x5B // pop  rbx  (58 + rbx_id=3)
#define x64_op_PUSH_RDX 0x52 // push rdx  (50 + rdx_id=2)
#define x64_op_POP_RDX  0x5A // pop  rdx  (58 + rdx_id=2)

// --- Composite Instruction Macros ---
// Each maps directly to the emit8/emit32/emit64 calls in compile_action.

// Stack Machine Operations
IA_ void x64_XCHG_RAX_RDX() { emit8(x64_REX); emit8(x64_op_XCHG_rm_reg); emit8(x64_modrm_RAX_RDX); }
IA_ void x64_MOV_RDX_RAX()  { emit8(x64_REX); emit8(x64_op_MOV_rm_reg);  emit8(x64_modrm_RAX_RDX); } // DUP
IA_ void x64_MOV_RAX_RDX()  { emit8(x64_REX); emit8(x64_op_MOV_rm_reg);  emit8(x64_modrm_RDX_RAX); } // DROP
// Arithmetic (2-register stack: op RAX with RDX, result in RAX)
IA_ void x64_ADD_RAX_RDX()   { emit8(x64_REX); emit8(x64_op_ADD_rm_reg);   emit8(x64_modrm_RAX_RDX); }
IA_ void x64_SUB_RAX_RDX()   { emit8(x64_REX); emit8(x64_op_SUB_rm_reg);   emit8(x64_modrm_RAX_RDX); }
IA_ void x64_IMUL_RAX_RDX()  { emit8(x64_REX); emit8(x64_op_IMUL_reg_rm);  emit8(x64_op_IMUL_reg_rm2); emit8(x64_modrm_RAX_RDX); }
IA_ void x64_DEC_RAX()       { emit8(x64_REX); emit8(x64_op_UNARY);        emit8(x64_modrm(x64_mod_reg, x64_ext_DEC, x64_reg_RAX)); }
// Flag Operations (for conditional returns)
IA_ void x64_TEST_RAX_RAX() { emit8(x64_REX); emit8(x64_op_TEST_rm_reg);  emit8(x64_modrm_RAX_RAX); }
// Conditional Returns (TEST must precede these)
IA_ void x64_RET_IF_ZERO() { x64_TEST_RAX_RAX(); emit8(x64_op_JNZ_rel8); emit8(0x01); emit8(x64_op_RET); } // JNZ skips the RET if RAX != 0, so RET only fires when RAX == 0
IA_ void x64_RET_IF_SIGN() { x64_TEST_RAX_RAX(); emit8(x64_op_JNS_rel8); emit8(0x01); emit8(x64_op_RET); } // JNS skips the RET if RAX >= 0, so RET only fires when RAX < 0

// Tape Drive Memory (Preemptive Scatter via RBX base pointer)
IA_ void x64_FETCH() {
	emit8(x64_REX);
	emit8(x64_op_MOV_reg_rm);
	emit8(x64_modrm_RAX_sib);
	emit8(x64_sib_tape);
}
IA_ void x64_STORE() {
	emit8(x64_REX);
	emit8(x64_op_MOV_rm_reg);
	emit8(x64_modrm_RDX_sib);
	emit8(x64_sib_tape);
}
// Indirect call through RAX (EXECUTE primitive)
IA_ void x64_CALL_RAX() {
	emit8(x64_op_UNARY);
	emit8(x64_modrm(x64_mod_reg, x64_ext_CALL, x64_reg_RAX));
}
IA_ void x64_RET() { emit8(x64_op_RET); } // RET

// Forward-jump placeholder: emits JMP rel32 with a zero displacement and writes
// the offset of the displacement field into *offset_out so it can be patched later.
IA_ void x64_JMP_fwd_placeholder(U4* offset_out) {
	emit8(x64_op_JMP_rel32);
	offset_out[0] = u4_(code_arena.used);
	emit32(0);
}
// Patch a previously emitted forward-jump placeholder.
// offset is the value written by x64_JMP_fwd_placeholder; the displacement is
// computed relative to the end of the 4-byte field (i.e. offset + 4).
IA_ void x64_patch_fwd(U4 offset) {
	u4_r(code_arena.start + offset)[0] = u4_(code_arena.used) - (offset + 4);
}

// Conditional Forward Jump (IF)
IA_ void x64_JMP_IF_ZERO_fwd_placeholder(U4* offset_out) {
	x64_TEST_RAX_RAX();
	emit8(0x0F); emit8(0x84); // JZ rel32
	offset_out[0] = u4_(code_arena.used);
	emit32(0);
}

// Unconditional Backward Jump (RECURSE)
IA_ void x64_JMP_back(U4 target) {
	emit8(x64_op_JMP_rel32);
	S4 rel32 = s4_(target) - s4_(code_arena.used + 4);
	emit32(u4_(rel32));
}

// JIT Entry Prologue: save RBX, load vm_globals ptr from RCX, restore RAX/RDX state
// vm_globals[14] = RAX save slot (14 * 8 = 0x70)
// vm_globals[15] = RDX save slot (15 * 8 = 0x78)
#define x64_vm_rax_slot 0x70
#define x64_vm_rdx_slot 0x78

IA_ void x64_JIT_PROLOGUE() {
		emit8(x64_op_PUSH_RBX);
		emit8(x64_REX); emit8(x64_op_MOV_rm_reg);  emit8(x64_modrm_RCX_RBX);
		emit8(x64_REX); emit8(x64_op_MOV_reg_rm);  emit8(x64_modrm_RAX_mem_disp8_RBX); emit8(x64_vm_rax_slot);
		emit8(x64_REX); emit8(x64_op_MOV_reg_rm);  emit8(x64_modrm_RDX_mem_disp8_RBX); emit8(x64_vm_rdx_slot);
}
// JIT Exit Epilogue: save RAX/RDX state back, restore RBX, return
IA_ void x64_JIT_EPILOGUE() {
	emit8(x64_REX); emit8(x64_op_MOV_rm_reg); emit8(x64_modrm_RAX_mem_disp8_RBX); emit8(x64_vm_rax_slot);
	emit8(x64_REX); emit8(x64_op_MOV_rm_reg); emit8(x64_modrm_RDX_mem_disp8_RBX); emit8(x64_vm_rdx_slot);
	emit8(x64_op_POP_RBX);
	emit8(x64_op_RET);
}
// Win64 FFI Dance: align RSP, allocate 32 bytes shadow space
// sub rsp, 40  (32 shadow + 8 to realign since we pushed RDX)
#define x64_ffi_shadow_space 0x28
IA_ void x64_FFI_PROLOGUE() {
	emit8(x64_op_PUSH_RDX);
	emit8(x64_REX); emit8(x64_op_ARITH_imm8);
	emit8(x64_modrm(x64_mod_reg, x64_ext_SUB, x64_reg_RSP));
	emit8(x64_ffi_shadow_space);
}
// Map 2-register stack and tape drive into Win64 ABI argument registers
// RCX = RAX (arg1 = Top of Stack)
// RDX = RDX (arg2 = Next of Stack, already in place)
// R8  = vm_globals[0]
// R9  = vm_globals[1]
#define x64_FFI_MAP_ARGS() \
		do { \
				emit8(x64_REX);   emit8(x64_op_MOV_rm_reg);  emit8(x64_modrm_RAX_RCX); \
				emit8(x64_REX_R); emit8(x64_op_MOV_reg_rm);  emit8(x64_modrm(x64_mod_mem, x64_reg_R8,  x64_reg_RBX)); \
				emit8(x64_REX_R); emit8(x64_op_MOV_reg_rm);  emit8(x64_modrm(x64_mod_mem_disp8, x64_reg_R9, x64_reg_RBX)); emit8(0x08); \
		} while(0)

// Load absolute 64-bit function address into R10 and call it
#define x64_FFI_CALL_ABS(abs_addr) \
		do { \
				emit8(x64_REX_B); emit8(x64_op_MOV_r10_imm64); \
				emit32(u4_(u8_(abs_addr) & 0xFFFFFFFF)); \
				emit32(u4_(u8_(abs_addr) >> 32)); \
				emit8(0x41); emit8(x64_op_UNARY); \
				emit8(x64_modrm(x64_mod_reg, x64_ext_CALL, x64_reg_R10)); \
		} while(0)

// Restore RSP and RDX after FFI call
#define x64_FFI_EPILOGUE() \
		do { \
				emit8(x64_REX); emit8(x64_op_ARITH_imm8); \
				emit8(x64_modrm(x64_mod_reg, x64_ext_ADD, x64_reg_RSP)); \
				emit8(x64_ffi_shadow_space); \
				emit8(x64_op_POP_RDX); \
		} while(0)

#pragma endregion x64 Emission DSL

internal void compile_action(U4 val) 
{
	if (val >= 0x10000) {
		U4 p = val - 0x10000;
		if (p == PRIM_SWAP) { 
			x64_XCHG_RAX_RDX();
			pad32();
			return;
		} 
		else if (p == PRIM_MULT) { 
			x64_IMUL_RAX_RDX();
			pad32();
			return;
		} 
		else if (p == PRIM_ADD) { 
			x64_ADD_RAX_RDX();
			pad32();
			return;
		} 
		else if (p == PRIM_SUB) { 
			x64_SUB_RAX_RDX();
			pad32();
			return;
		} 
		else if (p == PRIM_FETCH) {
			x64_FETCH();
			pad32();
			return;
		} 
		else if (p == PRIM_DEC) { 
			x64_DEC_RAX();
			pad32();
			return;
		} 
		else if (p == PRIM_STORE) {
			x64_STORE();
			pad32();
			return;
		} 
		else if (p == PRIM_RET_Z) { 
			x64_RET_IF_ZERO();
			pad32();
			return;
		} 
		else if (p == PRIM_RET_S) { 
			x64_RET_IF_SIGN();
			pad32();
			return;
		} 
		else if (p == PRIM_RET) { 
			emit8(x64_op_RET);
			pad32();
			return;
		} 
		else if (p == PRIM_DUP) { 
			x64_MOV_RDX_RAX();
			pad32();
			return;
		} 
		else if (p == PRIM_DROP) { 
			x64_MOV_RAX_RDX();
			pad32();
			return;
		} 
		else if (p == PRIM_EXECUTE) {
			x64_CALL_RAX();
			pad32();
			return;
		} 
		else if (p == PRIM_PRINT) { 
			x64_FFI_PROLOGUE();
			x64_FFI_MAP_ARGS();
			x64_FFI_CALL_ABS(u8_(& ms_builtin_print));
			x64_FFI_EPILOGUE();
			pad32();
			return;
		}
	}
	
	if (val > 0 && val < 0x10000) {
		U4 target = tape_to_code_offset[val];
		pad32(); 
		S4 rel32  = s4_(target) - s4_(code_arena.used + 5);
		emit8(x64_op_CALL_rel32); 
		emit32(u4_(rel32));
		pad32();
	}
}


IA_ void compile_and_run_tape(void)
{
	farena_reset(& code_arena);
	log_count     = 0;
	gdi_log_count = 0;

	x64_JIT_PROLOGUE();

	U4*r tape_ptr      = u4_r(tape_arena.start);
	U8*r anno_ptr      = u8_r(anno_arena.start);
	B4   in_def        = false;
	U4   def_jmp_offset = 0;
	U4   current_def_idx = 0;

	B4   in_lambda         = false;
	U4   lambda_jmp_offset = 0;

	U4   ctrl_stack[32] = {0};
	U4   ctrl_depth = 0;

	U8 end_idx = run_full ? (tape_arena.used / sizeof(U4)) : (cursor_idx + 1);
	for (U8 i = 0; i < end_idx; i++)
	{
		U4 tag = unpack_tag(tape_ptr[i]);
		U4 val = unpack_val(tape_ptr[i]);

		B4 is_terminator = (tag == STag_Define || tag == STag_Imm);

		if (in_lambda && (is_terminator || tag == STag_Lambda)) {
			x64_RET();
			pad32();
			x64_patch_fwd(lambda_jmp_offset);
			in_lambda = false;
		}

		if (in_def && is_terminator) {
			x64_RET();
			pad32();
			x64_patch_fwd(def_jmp_offset);
			in_def = false;
		}

		if (tag == STag_Define)
		{
			pad32();
			x64_JMP_fwd_placeholder(& def_jmp_offset);
			pad32();
			in_def = true;
			current_def_idx = i;

			tape_to_code_offset[i] = code_arena.used;

			x64_XCHG_RAX_RDX();
			pad32();
		}
		else if (tag == STag_Lambda)
		{
			char* name = (char*)& anno_ptr[i];
			char val_hex[9];
			u64_to_hex(val, val_hex, 8);
			val_hex[8] = '\0';
			KTL_Slot_Str8 call_log_table[] = {
				{ ktl_str8_key("name"), str8(name) },
				{ ktl_str8_key("val"),  str8(val_hex) },
			};
			debug_log(str8("Compiling lambda: <name> (val: <val>)"), ktl_str8_from_arr(call_log_table));

			// mov rdx, rax  (save old rax into rdx)
			x64_MOV_RDX_RAX();
			// mov rax, imm64  (placeholder for lambda body address)
			emit8(x64_REX);
			emit8(x64_op_MOV_rax_imm64);
			U4 rax_imm_offset = code_arena.used;
			emit64(0);
			pad32();

			// jmp rel32 over lambda body
			x64_JMP_fwd_placeholder(& lambda_jmp_offset);
			pad32();
			in_lambda = true;

			// Patch the mov rax, imm64 with the actual lambda body address
			U8 lambda_addr = u8_(code_arena.start + code_arena.used);
			u8_r(code_arena.start + rax_imm_offset)[0] = lambda_addr;
		}
		else if (tag == STag_Call || tag == STag_Imm)
		{
			if (val == 0x10000 + PRIM_IF) {
				x64_JMP_IF_ZERO_fwd_placeholder(& ctrl_stack[ctrl_depth++]);
				pad32();
			} 
			else if (val == 0x10000 + PRIM_END) {
				if (ctrl_depth > 0) {
					U4 offset = ctrl_stack[--ctrl_depth];
					x64_patch_fwd(offset);
				}
				pad32();
			}
			else if (val == 0x10000 + PRIM_RECURSE) {
				if (in_def) {
					x64_JMP_back(tape_to_code_offset[current_def_idx]);
				}
				pad32();
			}
			else {
				compile_action(val);
			}
		}
		else if (tag == STag_Data)
		{
			x64_MOV_RDX_RAX();
			emit8(x64_REX);
			emit8(x64_op_MOV_rm_imm32);
			emit8(x64_modrm(x64_mod_reg, 0, x64_reg_RAX));
			emit32(val);
			pad32();
		}
	}

	if (in_lambda) {
		x64_RET();
		pad32();
		x64_patch_fwd(lambda_jmp_offset);
	}
	if (in_def) {
		x64_RET();
		pad32();
		x64_patch_fwd(def_jmp_offset);
	}

	x64_JIT_EPILOGUE();

	typedef void JIT_Func(U8* globals_ptr);
	JIT_Func* func = (JIT_Func*)code_arena.start;
	func(vm_globals);

	vm_rax = vm_globals[14];
	vm_rdx = vm_globals[15];

	char rax_hex[9]; u64_to_hex(vm_rax, rax_hex, 8); rax_hex[8] = '\0';
	char rdx_hex[9]; u64_to_hex(vm_rdx, rdx_hex, 8); rdx_hex[8] = '\0';
	KTL_Slot_Str8 post_jit_log_table[] = {
		{ ktl_str8_key("rax"), str8(rax_hex) },
		{ ktl_str8_key("rdx"), str8(rdx_hex) },
	};
	debug_log(str8("JIT finished. RAX: <rax>, RDX: <rdx>"), ktl_str8_from_arr(post_jit_log_table));
}




#undef r
#undef v
#undef expect
#include "microui.c"
#undef expect
#define expect(x,y)   __builtin_expect(x, y)                  // so compiler knows the common path
#define r restrict
#define v volatile

global mu_Context mu_ctx;

internal int text_width_cb(mu_Font font, const char *str, int len) {
	if (len == -1) { len = 0; while (str[len]) len++; }
	return len * 11; // Approx 11px per char for Consolas 20
}

internal int text_height_cb(mu_Font font) {
	return 20; // Consolas 20 height
}

internal void gdi_draw_rect(void* hdc, mu_Rect rect, mu_Color color) {
	U1 red   = ((U1*)&color)[0];
	U1 green = ((U1*)&color)[1];
	U1 blue  = ((U1*)&color)[2];
	void* hBrush = ms_create_solid_brush((red) | (green << 8) | (blue << 16));
	void* hOldBrush = ms_select_object(hdc, hBrush);
	ms_rectangle(hdc, rect.x - 1, rect.y - 1, rect.x + rect.w + 1, rect.y + rect.h + 1);
	ms_select_object(hdc, hOldBrush);
	ms_delete_object(hBrush);
}

internal void render_microui(void* hdc) {
	mu_Command *cmd = NULL;
	while (mu_next_command(&mu_ctx, &cmd)) {
		switch (cmd->type) {
			case MU_COMMAND_TEXT: {
				U1 red   = ((U1*)&cmd->text.color)[0];
				U1 green = ((U1*)&cmd->text.color)[1];
				U1 blue  = ((U1*)&cmd->text.color)[2];
				ms_set_text_color(hdc, (red) | (green << 8) | (blue << 16));
				int len = 0; while (cmd->text.str[len]) len++;
				ms_text_out_a(hdc, cmd->text.pos.x, cmd->text.pos.y, cmd->text.str, len);
				break;
			}
			case MU_COMMAND_RECT: {
				gdi_draw_rect(hdc, cmd->rect.rect, cmd->rect.color);
				break;
			}
			case MU_COMMAND_ICON: {
				gdi_draw_rect(hdc, cmd->icon.rect, cmd->icon.color);
				break;
			}
			case MU_COMMAND_CLIP: {
				break;
			}
		}
	}
}

S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) 
{
	U8 tape_count = tape_arena.used / sizeof(U4);
	U4*r tape_ptr = u4_r(tape_arena.start);
	switch (msg)  {
	case MS_WM_CHAR: {
		char buf[2] = { (char)wparam, 0 };
		mu_input_text(&mu_ctx, buf);
		
		if (editor_mode != MODE_EDIT) { ms_invalidate_rect(hwnd, nullptr, true); return 0; }
		
		U4 t   = tape_ptr[cursor_idx];
		U4 tag = unpack_tag(t);
		U4 val = unpack_val(t);
		U1 c   = u1_(wparam);
		
		B4 should_skip = c < 32 || (c == 'e' && mode_switch_now);
		if (should_skip) { mode_switch_now = false; ms_invalidate_rect(hwnd, nullptr, true); return 0; }

		if (tag == STag_Data) {
			U4 digit = 16;
			if (c >= '0' && c <= '9') digit = c - '0';
			if (c >= 'a' && c <= 'f') digit = c - 'a' + 10;
			if (c >= 'A' && c <= 'F') digit = c - 'A' + 10;
			if (digit < 16) {
				val = ((val << 4) | digit) & 0x0FFFFFFF;
				tape_ptr[cursor_idx] = pack_token(tag, val);
			}
		} 
		else if (tag != STag_Format) {
			U8*r  anno_ptr = u8_r(anno_arena.start);
			char* anno_str = (char*) & anno_ptr[cursor_idx];
			int    len = 0;
			while (len < 8 && anno_str[len] != '\0' && anno_str[len] != ' ') len ++;
			if    (len < 8) {
				anno_str[len] = (char)c;
				for (int i = len + 1; i < 8; i++) anno_str[i] = '\0';

				if (tag == STag_Call || tag == STag_Imm || tag == STag_Define) {
					U4 new_val = resolve_name_to_index(anno_str);
					tape_ptr[cursor_idx] = pack_token(tag, new_val);
					if (tag == STag_Define) relink_tape();
				}
			}
		}
		vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals));
		compile_and_run_tape();
		ms_invalidate_rect(hwnd, nullptr, true);
		return 0;
	}
	case MS_WM_MOUSEMOVE: {
		mu_input_mousemove(&mu_ctx, (S2)(lparam & 0xFFFF), (S2)((lparam >> 16) & 0xFFFF));
		ms_invalidate_rect(hwnd, nullptr, true);
		return 0;
	}
	case MS_WM_LBUTTONDOWN: {
		mu_input_mousedown(&mu_ctx, (S2)(lparam & 0xFFFF), (S2)((lparam >> 16) & 0xFFFF), MU_MOUSE_LEFT);
		ms_invalidate_rect(hwnd, nullptr, true);
		return 0;
	}
	case MS_WM_LBUTTONUP: {
		mu_input_mouseup(&mu_ctx, (S2)(lparam & 0xFFFF), (S2)((lparam >> 16) & 0xFFFF), MU_MOUSE_LEFT);
		ms_invalidate_rect(hwnd, nullptr, true);
		return 0;
	}
	case MS_WM_MOUSEWHEEL: {
		mu_input_scroll(&mu_ctx, 0, ((S2)((wparam >> 16) & 0xFFFF)) / -30);
		ms_invalidate_rect(hwnd, nullptr, true);
		return 0;
	}
	case MS_WM_KEYDOWN: {
		int key = 0;
		if (wparam == MS_VK_BACK) key = MU_KEY_BACKSPACE;
		if (wparam == MS_VK_RETURN) key = MU_KEY_RETURN;
		if (wparam == 0x10) key = MU_KEY_SHIFT;
		if (wparam == 0x11) key = MU_KEY_CTRL;
		if (wparam == 0x12) key = MU_KEY_ALT;
		if (key) mu_input_keydown(&mu_ctx, key);

		if (wparam == 0x45 && editor_mode == MODE_NAV) { 
			editor_mode = MODE_EDIT;
			mode_switch_now = true;
			ms_invalidate_rect(hwnd, nullptr, true);
			return 0; 
		}
		if (wparam == 0x1B && editor_mode == MODE_EDIT) { 
			editor_mode = MODE_NAV;
			relink_tape();
			ms_invalidate_rect(hwnd, nullptr, true);
			return 0;
		}
		if (editor_mode == MODE_EDIT) {
			if (wparam == MS_VK_BACK) {
				U4 t   = tape_ptr[cursor_idx];
				U4 tag = unpack_tag(t);
				U4 val = unpack_val(t);
				if (tag == STag_Data) {
					val                  = val >> 4;
					tape_ptr[cursor_idx] = pack_token(tag, val);
				} 
				else if (tag != STag_Format) {
					U8*r  anno_ptr = u8_r(anno_arena.start);
					char* anno_str = (char*) & anno_ptr[cursor_idx];
					int    len = 0;
					while (len < 8 && anno_str[len] != '\0' && anno_str[len] != ' ') len ++;
					if    (len > 0) {
						anno_str[len - 1] = '\0';
						if (tag == STag_Call || tag == STag_Imm || tag == STag_Define) {
							U4 new_val = resolve_name_to_index(anno_str);
							tape_ptr[cursor_idx] = pack_token(tag, new_val);
							if (tag == STag_Define) relink_tape();
						}
					}
				}
				vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals));
				compile_and_run_tape();
				ms_invalidate_rect(hwnd, nullptr, true);
			}
			return 0; 
		}
		
		if (wparam == MS_VK_RIGHT && cursor_idx < tape_count - 1) cursor_idx ++;
		if (wparam == MS_VK_LEFT  && cursor_idx > 0)              cursor_idx --;
		
		if (wparam == MS_VK_UP) {
			U8     line_start = cursor_idx;
			while (line_start > 0 && unpack_tag(tape_ptr[line_start - 1]) != STag_Format) line_start--;
			if    (line_start > 0) {
				U8 col             = cursor_idx - line_start;
				U8 prev_line_start = line_start - 1;
				while (prev_line_start > 0 && unpack_tag(tape_ptr[prev_line_start - 1]) != STag_Format) prev_line_start--;
				U8 prev_line_len = (line_start - 1) - prev_line_start;
				cursor_idx = prev_line_start + (col < prev_line_len ? col : prev_line_len);
			}
		}
		if (wparam == MS_VK_DOWN) {
			U8 line_start = cursor_idx;
			while (line_start > 0 && unpack_tag(tape_ptr[line_start - 1]) != STag_Format) line_start --;
			U8 col = cursor_idx - line_start;
			U8     next_line_start = cursor_idx;
			while (next_line_start < tape_count && unpack_tag(tape_ptr[next_line_start]) != STag_Format) next_line_start ++;
			if    (next_line_start < tape_count) {
				next_line_start ++; 
				U8     next_line_end = next_line_start;
				while (next_line_end < tape_count && unpack_tag(tape_ptr[next_line_end]) != STag_Format) next_line_end ++;
				U8     next_line_len = next_line_end - next_line_start;
				cursor_idx = next_line_start + (col < next_line_len ? col : next_line_len);
			}
		}
		
		if (wparam == MS_VK_PRIOR) { scroll_y_offset -= 100; if (scroll_y_offset < 0) scroll_y_offset = 0; }
		if (wparam == MS_VK_NEXT)  { scroll_y_offset += 100; }
		if (wparam == MS_VK_F5)    { run_full = !run_full; }
		if (wparam == MS_VK_F1)    { save_cartridge(); }
		if (wparam == MS_VK_F2)    { load_cartridge(); ms_invalidate_rect(hwnd, nullptr, true); }

		if (wparam == MS_VK_TAB) {
			U4 t   = tape_ptr[cursor_idx];
			U4 tag = (unpack_tag(t) + 1) % STag_Count;
			tape_ptr[cursor_idx] = pack_token(tag, unpack_val(t));
		}
		else if (wparam == MS_VK_BACK) 
		{
			U8 delete_idx = cursor_idx;
			B4 is_shift = (ms_get_async_key_state(MS_VK_SHIFT) & 0x8000) != 0;
			if (is_shift == false) {
				if (cursor_idx > 0) {
					delete_idx = cursor_idx - 1;
					cursor_idx--;
				}
				else return 0;
			}
			if (tape_count > 0) {
				U8*r anno_ptr = u8_r(anno_arena.start);
				for (U8 i = delete_idx; i < tape_count - 1; i ++) {
					tape_ptr[i] = tape_ptr[i + 1];
					anno_ptr[i] = anno_ptr[i + 1];
				}
				tape_arena.used -= sizeof(U4);
				anno_arena.used -= sizeof(U8);
			}
			relink_tape();
		} 
		else if (wparam == MS_VK_SPACE || wparam == MS_VK_RETURN) {
			B4 is_shift   = (ms_get_async_key_state(MS_VK_SHIFT) & 0x8000) != 0;
			U8 insert_idx = cursor_idx;
			if (is_shift) insert_idx ++;

			if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) {
				U8*r anno_ptr = u8_r(anno_arena.start);
				for (U8 i = tape_count; i > insert_idx; i --) {
					tape_ptr[i] = tape_ptr[i-1];
					anno_ptr[i] = anno_ptr[i-1];
				}
				if (wparam == MS_VK_RETURN) {
					tape_ptr[insert_idx] = pack_token(STag_Format, 0xA);
					anno_ptr[insert_idx] = 0;
				} else {
					tape_ptr[insert_idx] = pack_token(STag_Comment, 0);
					anno_ptr[insert_idx] = 0;
				}
				if (is_shift) cursor_idx ++;
				tape_arena.used += sizeof(U4);
				anno_arena.used += sizeof(U8);
			}
		}
		
		vm_rax = 0; vm_rdx = 0;
		mem_zero(u8_(vm_globals), sizeof(vm_globals));
		
		compile_and_run_tape();
		
		ms_invalidate_rect(hwnd, nullptr, true);
		return 0;
	}
	case MS_WM_KEYUP: {
		int key = 0;
		if (wparam == MS_VK_BACK) key = MU_KEY_BACKSPACE;
		if (wparam == MS_VK_RETURN) key = MU_KEY_RETURN;
		if (wparam == 0x10) key = MU_KEY_SHIFT;
		if (wparam == 0x11) key = MU_KEY_CTRL;
		if (wparam == 0x12) key = MU_KEY_ALT;
		if (key) mu_input_keyup(&mu_ctx, key);
		ms_invalidate_rect(hwnd, nullptr, true);
		return 0;
	}
	case MS_WM_SIZE: {
		ms_invalidate_rect(hwnd, nullptr, true);
		return 0;
	}
	case MS_WM_ERASEBKGND: {
		return 1;
	}
	case MS_WM_PAINT: {
		mu_begin(&mu_ctx);

		if (mu_begin_window(&mu_ctx, "ColorForth Source Tape", mu_rect(10, 10, 900, 480))) 
		{
			U4*r tape_ptr = u4_r(tape_arena.start);
			U8*r anno_ptr = u8_r(anno_arena.start);

			S4 start_x = 5, start_y = 5, spacing_x = 6, spacing_y = 26;
			S4 x = start_x, y = start_y;

			for (U8 i = 0; i < tape_count; i++) 
			{
				U4 t    = tape_ptr[i];
				U4 tag  = unpack_tag(t);
				U4 val  = unpack_val(t);
				U8 anno = anno_ptr[i];

				if (tag == STag_Format && val == 0xA) {
					x = start_x;
					y += spacing_y;
					continue;
				}

				U4 color_u32 = tag_colors[tag];
				const char* prefix = tag_prefixes[tag];
				
				char val_str[9]; 
				if (tag == STag_Data) {
					u64_to_hex(val, val_str, 6);
					val_str[6] = '\0';
				} 
				else 
				{
					char* a_str = (char*) & anno;
					for(int c=0; c<8; c++) {
						val_str[c] = a_str[c] ? a_str[c] : ' ';
					}
					val_str[8] = '\0';
				}
				char out_buf[12];
				out_buf[0] = prefix[0];
				out_buf[1] = ' ';
				mem_copy(u8_(out_buf + 2), u8_(val_str), 8);
				out_buf[10] = '\0';

				int btn_w = 20 + text_width_cb(NULL, out_buf, 10);
				
				// auto-wrap
				mu_Container* current_window = mu_get_current_container(&mu_ctx);
				if (x + btn_w > current_window->body.w - 15) {
					x = start_x;
					y += spacing_y;
				}

				mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(color_u32 & 0xFF, (color_u32 >> 8) & 0xFF, (color_u32 >> 16) & 0xFF, 255);
				
				if (i == cursor_idx && editor_mode == MODE_EDIT) {
					mu_ctx.style->colors[MU_COLOR_BUTTON] = mu_color(0x56, 0x3B, 0x1E, 255); // Dark Orange
				} else if (i == cursor_idx && editor_mode == MODE_NAV) {
					mu_ctx.style->colors[MU_COLOR_BUTTON] = mu_color(0x3B, 0x46, 0x56, 255); // Dark Blue
				} else {
					mu_ctx.style->colors[MU_COLOR_BUTTON] = mu_color(0x1E, 0x1E, 0x1E, 255); // Dark Gray
				}
				
				mu_layout_set_next(&mu_ctx, mu_rect(x, y, btn_w, 22), 1);
				
				if (mu_button(&mu_ctx, out_buf)) {
					cursor_idx = i;
					editor_mode = MODE_NAV;
				}

				x += btn_w + spacing_x;

				mu_ctx.style->colors[MU_COLOR_BUTTON] = mu_color(75, 75, 75, 255);
				mu_ctx.style->colors[MU_COLOR_TEXT]   = mu_color(230, 230, 230, 255);
			}
				
			// Dummy element to ensure scrolling bounds are correct
			mu_layout_set_next(&mu_ctx, mu_rect(start_x, y + spacing_y, 10, 10), 1);
			mu_draw_rect(&mu_ctx, mu_layout_next(&mu_ctx), mu_color(0,0,0,0));

			mu_end_window(&mu_ctx);
		}

		if (mu_begin_window(&mu_ctx, "Compiler & Status", mu_rect(10, 500, 350, 200))) {
			char jit_str[64] = "Mode: Incremental | JIT Size: 0x000 bytes";
			if (run_full) mem_copy(u8_(jit_str + 6), u8_("Full       "), 11);
			u64_to_hex(code_arena.used, jit_str + 32, 3);
			mu_layout_row(&mu_ctx, 1, (int[]){-1}, 0);
			mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(170, 170, 170, 255);
			mu_text(&mu_ctx, "2-Reg Stack x86-64 Emitter");
			mu_text(&mu_ctx, "[F5] Toggle Run | [PgUp/PgDn] Scroll");
			mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(255, 255, 255, 255);
			mu_text(&mu_ctx, jit_str);
			if (tape_count > 0 && cursor_idx < tape_count) {
				U4          cur_tag  = unpack_tag(tape_ptr[cursor_idx]);
				const char* tag_name = tag_names [cur_tag];
				U4         cur_color = tag_colors[cur_tag];
				char semantics_str[64] = "Current Tag: ";
				U4   name_len          = 0;
				while (tag_name[name_len]) {
					semantics_str[13 + name_len] = tag_name[name_len];
					name_len ++;
				}
				semantics_str[13 + name_len] = '\0';
				mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(cur_color & 0xFF, (cur_color >> 8) & 0xFF, (cur_color >> 16) & 0xFF, 255);
				mu_text(&mu_ctx, semantics_str);
			}
			mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(230, 230, 230, 255);
			mu_end_window(&mu_ctx);
		}
		if (mu_begin_window(&mu_ctx, "Registers & Globals", mu_rect(370, 500, 350, 200))) {
			char state_str[64] = "RAX: 00000000 | RDX: 00000000";
			u64_to_hex(vm_rax, state_str + 5, 8);
			u64_to_hex(vm_rdx, state_str + 21, 8);
			mu_layout_row(&mu_ctx, 1, (int[]){-1}, 0);
			mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(161, 186, 148, 255); // #94BAA1 mapped roughly
			mu_text(&mu_ctx, state_str);
					
			for (int i=0; i < 4; i ++) {
				char glob_str[32] = "[0]: 00000000";
				glob_str[1] = '0' + i;
				u64_to_hex(vm_globals[i], glob_str + 5, 8);
				mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(84, 164, 214, 255); // #D6A454 rough mapping to bgr?
				// actually #D6A454 is R=D6(214) G=A4(164) B=54(84) but tag colors are 0x00BBGGRR, so 54(R) A4(G) D6(B).
				// It was orange before, so 54, 164, 214.
				mu_text(&mu_ctx, glob_str);
			}
			mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(230, 230, 230, 255);
			mu_end_window(&mu_ctx);
		}
		if (mu_begin_window(&mu_ctx, "Print Log", mu_rect(730, 500, 250, 200))) {
			mu_layout_row(&mu_ctx, 1, (int[]){-1}, 0);
			mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(161, 186, 148, 255);
			for (int i = 0; i<log_count && i < 16; i ++) {
				char log_str[32] = "00000000";
				u64_to_hex(log_buffer[i], log_str, 8);
				mu_text(&mu_ctx, log_str);
			}
			mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(230, 230, 230, 255);
			mu_end_window(&mu_ctx);
		}

		mu_end(&mu_ctx);

		MS_PAINTSTRUCT ps;
		void* hdc      = ms_begin_paint(hwnd, & ps);
		
		MS_RECT rect;
		ms_get_client_rect(hwnd, &rect);
		S4 width = rect.right - rect.left;
		S4 height = rect.bottom - rect.top;

		void* memDC = ms_create_compatible_dc(hdc);
		void* memBitmap = ms_create_compatible_bitmap(hdc, width, height);
		void* oldBitmap = ms_select_object(memDC, memBitmap);

		void* hFont    = ms_create_font_a(20, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, "Consolas");
		void* hOldFont = ms_select_object(memDC, hFont);

		ms_set_bk_mode(memDC, 1); 

		void* hBgBrush = ms_create_solid_brush(0x00222222);
		ms_select_object(memDC, hBgBrush);
		ms_rectangle(memDC, -1, -1, width + 2, height + 2);

		render_microui(memDC);

		ms_bit_blt(hdc, 0, 0, width, height, memDC, 0, 0, MS_SRCCOPY);

		ms_select_object(memDC, hOldFont);
		ms_delete_object(hBgBrush);
		ms_delete_object(hFont);
		
		ms_select_object(memDC, oldBitmap);
		ms_delete_object(memBitmap);
		ms_delete_dc(memDC);

		ms_end_paint(hwnd, & ps);
		return 0;
	}
	case MS_WM_DESTROY: { ms_post_quit_message(0); return 0; }
	}
	return ms_def_window_proc_a(hwnd, msg, wparam, lparam);
}

int main(void) {
	Slice tape_mem = slice_ut_(u8_(ms_virtual_alloc(nullptr, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE)), 64 * 1024);
	Slice anno_mem = slice_ut_(u8_(ms_virtual_alloc(nullptr, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE)), 64 * 1024);
	Slice code_mem = slice_ut_(u8_(ms_virtual_alloc(nullptr, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_EXECUTE_READWRITE)), 64 * 1024);
	if (! tape_mem.ptr || ! anno_mem.ptr || ! code_mem.ptr) ms_exit_process(1);
	
	farena_init(& tape_arena, tape_mem);
	farena_init(& anno_arena, anno_mem);
	farena_init(& code_arena, code_mem);

	mu_init(&mu_ctx);
	mu_ctx.text_width = text_width_cb;
	mu_ctx.text_height = text_height_cb;

	// Factorial
	{
		scatter(pack_token(STag_Comment, 0), "INIT    "); 
		scatter(pack_token(STag_Data,    5), 0);      
		scatter(pack_token(STag_Data,    0), 0);      
		scatter(pack_token(STag_Imm,     0), "STORE   ");    
		
		scatter(pack_token(STag_Data,    1), 0);      
		scatter(pack_token(STag_Data,    1), 0);      
		scatter(pack_token(STag_Imm,     0), "STORE   ");    
		
		scatter(pack_token(STag_Format,  0xA), 0); 
		
		scatter(pack_token(STag_Define,  0), "F_STEP  "); 
		scatter(pack_token(STag_Data,    0), 0);  
		scatter(pack_token(STag_Call,    0), "FETCH   "); 
		scatter(pack_token(STag_Call,    0), "RET_IF_Z"); 
		scatter(pack_token(STag_Format,  0xA), 0); 
		
		scatter(pack_token(STag_Data,    1), 0);  
		scatter(pack_token(STag_Call,    0), "FETCH   "); 
		scatter(pack_token(STag_Data,    0), 0);  
		scatter(pack_token(STag_Call,    0), "FETCH   "); 
		scatter(pack_token(STag_Call,    0), "MULT    "); 
		scatter(pack_token(STag_Data,    1), 0);  
		scatter(pack_token(STag_Call,    0), "STORE   "); 
		scatter(pack_token(STag_Format,  0xA), 0); 
		
		scatter(pack_token(STag_Data,    0), 0);  
		scatter(pack_token(STag_Call,    0), "FETCH   "); 
		scatter(pack_token(STag_Call,    0), "DEC     "); 
		scatter(pack_token(STag_Data,    0), 0);  
		scatter(pack_token(STag_Call,    0), "STORE   "); 
		
		scatter(pack_token(STag_Data,    1), 0);  
		scatter(pack_token(STag_Call,    0), "FETCH   "); 
		scatter(pack_token(STag_Call,    0), "PRINT   "); 
		
		scatter(pack_token(STag_Format,  0xA), 0); 
		
		scatter(pack_token(STag_Call,    0), "RECURSE "); 
		scatter(pack_token(STag_Format,  0xA), 0); 
		
		scatter(pack_token(STag_Imm,     0), "F_STEP  ");   
	}

	// IF TEST
	{
		scatter(pack_token(STag_Comment, 0), "IF TEST ");
		scatter(pack_token(STag_Format,  0xA), 0);
		scatter(pack_token(STag_Data,    0), 0); 
		scatter(pack_token(STag_Call,    0), "[       "); 
		scatter(pack_token(STag_Data,    99), 0);
		scatter(pack_token(STag_Call,    0), "PRINT   "); 
		scatter(pack_token(STag_Call,    0), "]       "); 
		scatter(pack_token(STag_Data,    11), 0);
		scatter(pack_token(STag_Call,    0), "PRINT   "); 
		scatter(pack_token(STag_Format,  0xA), 0);
		
		scatter(pack_token(STag_Data,    1), 0); 
		scatter(pack_token(STag_Call,    0), "[       "); 
		scatter(pack_token(STag_Data,    22), 0);
		scatter(pack_token(STag_Call,    0), "PRINT   "); 
		scatter(pack_token(STag_Call,    0), "]       "); 
		scatter(pack_token(STag_Format,  0xA), 0);
	}

	// Lambda test
	{
		scatter(pack_token(STag_Comment, 0), "LAMBDAS "); 
		scatter(pack_token(STag_Format,  0xA), 0); 
		
		// --- Store Lambda 1 (Square) in Global[0] ---
		scatter(pack_token(STag_Data,    0), 0);           
		scatter(pack_token(STag_Lambda,  0), "L_SQUARE");  
		// Lambda Body:
		scatter(pack_token(STag_Call,    0), "SWAP    ");  // Get the argument into RAX
		scatter(pack_token(STag_Call,    0), "DUP     ");  
		scatter(pack_token(STag_Call,    0), "MULT    ");  
		// Terminate Lambda, return to main scope, and prepare for STORE
		scatter(pack_token(STag_Imm,     0), "SWAP    ");  // RAX = 0, RDX = L_SQUARE_addr
		scatter(pack_token(STag_Call,    0), "STORE   ");  // Global[0] = L_SQUARE_addr
		scatter(pack_token(STag_Format,  0xA), 0); 

		// --- Store Lambda 2 (Double) in Global[1] ---
		scatter(pack_token(STag_Data,    1), 0);           
		scatter(pack_token(STag_Lambda,  0), "L_DOUBLE");  
		// Lambda Body:
		scatter(pack_token(STag_Call,    0), "SWAP    ");  // Get the argument into RAX
		scatter(pack_token(STag_Call,    0), "DUP     ");  
		scatter(pack_token(STag_Call,    0), "ADD     ");  
		// Terminate Lambda, return to main scope, and prepare for STORE
		scatter(pack_token(STag_Imm,     0), "SWAP    ");  // RAX = 1, RDX = L_DOUBLE_addr
		scatter(pack_token(STag_Call,    0), "STORE   ");  // Global[1] = L_DOUBLE_addr
		scatter(pack_token(STag_Format,  0xA), 0); 

		// --- Execute Lambda 1 (Square of 5) ---
		scatter(pack_token(STag_Comment, 0), "USE L1  "); 
		scatter(pack_token(STag_Data,    5), 0);           // Argument for lambda
		scatter(pack_token(STag_Data,    0), 0);           
		scatter(pack_token(STag_Call,    0), "FETCH   ");  // RAX = Global[0] (L_SQUARE_addr), RDX = 5
		scatter(pack_token(STag_Call,    0), "EXECUTE ");  // Calls L_SQUARE. Returns RAX = 25
		scatter(pack_token(STag_Call,    0), "PRINT   ");  // Prints 0x19 (25)
		scatter(pack_token(STag_Format,  0xA), 0); 

		// --- Execute Lambda 2 (Double of 5) ---
		scatter(pack_token(STag_Comment, 0), "USE L2  "); 
		scatter(pack_token(STag_Data,    5), 0);           // Argument for lambda
		scatter(pack_token(STag_Data,    1), 0);           
		scatter(pack_token(STag_Call,    0), "FETCH   ");  // RAX = Global[1] (L_DOUBLE_addr), RDX = 5
		scatter(pack_token(STag_Call,    0), "EXECUTE ");  // Calls L_DOUBLE. Returns RAX = 10
		scatter(pack_token(STag_Call,    0), "PRINT   ");  // Prints 0xA (10)
	}

	relink_tape();
	run_full = true;
	compile_and_run_tape();
	run_full = false;

	MS_WNDCLASSA wc;
	mem_fill(u8_(& wc), 0, sizeof(wc));
	wc.lpfnWndProc = win_proc;
	wc.hInstance = ms_get_stock_object(0);
	wc.lpszClassName = "ColorForthWindow";
	wc.hbrBackground = ms_get_stock_object(4);
	ms_register_class_a(& wc);

	void* hwnd = ms_create_window_ex_a(0, wc.lpszClassName, "Sourceless Global Memory Explorer", MS_WS_OVERLAPPEDWINDOW | MS_WS_VISIBLE, 100, 100, 1100, 750, nullptr, nullptr, wc.hInstance, nullptr);
	MS_MSG msg;
	while (ms_get_message_a(& msg, nullptr, 0, 0)) { ms_translate_message(& msg); ms_dispatch_message_a(& msg); }
	ms_exit_process(0);
	return 0;
}
