Compare commits

...

2 Commits

Author SHA1 Message Date
ed b4055d8067 progress 2026-02-20 16:29:32 -05:00
ed e1a97ae669 progress 2026-02-20 16:12:17 -05:00
2 changed files with 271 additions and 112 deletions
+238 -79
View File
@@ -52,9 +52,14 @@ global const char* tag_names[] = {
#define TOKENS_PER_ROW 8
#define MODE_NAV 0
#define MODE_EDIT 1
// The Tape Drive (Using FArena from duffle)
global FArena tape_arena;
global FArena anno_arena;
global U8 cursor_idx = 0;
global U4 editor_mode = MODE_NAV;
// Executable Code Arena (The JIT)
global FArena code_arena;
@@ -64,6 +69,20 @@ global U8 vm_rax = 0; // Top
global U8 vm_rdx = 0; // Next
global U8 vm_globals[16] = {0};
// Execution Mode & Logging
global B4 run_full = false;
global U8 log_buffer[16] = {0};
global U4 log_count = 0;
// UI State
global S4 scroll_y_offset = 0;
void ms_builtin_print(U8 val) {
if (log_count < 16) {
log_buffer[log_count++] = val;
}
}
// Dictionary
typedef struct {
U4 val;
@@ -87,11 +106,23 @@ void* memcpy(void* dest, const void* src, U8 count) {
}
#pragma clang optimize on
IA_ void scatter(U4 token) {
if (tape_arena.used + sizeof(U4) <= tape_arena.capacity) {
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*r ptr = C_(U4*r, tape_arena.start + tape_arena.used);
ptr[0] = token;
tape_arena.used += sizeof(U4);
U8*r aptr = C_(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);
}
}
@@ -144,6 +175,20 @@ internal void compile_action(U4 val) {
} else if (val == ID2('R','E')) { // RET
emit8(0xC3);
return;
} else if (val == ID2('P','R')) { // PRINT: call ms_builtin_print
emit8(0x51); // push rcx
emit8(0x52); // push rdx
emit8(0x48); emit8(0x83); emit8(0xEC); emit8(0x20); // sub rsp, 32
emit8(0x48); emit8(0x89); emit8(0xC1); // mov rcx, rax
emit8(0x49); emit8(0xB8); // mov r8, imm64
U8 addr = (U8)&ms_builtin_print;
emit32((U4)(addr & 0xFFFFFFFF));
emit32((U4)(addr >> 32));
emit8(0x41); emit8(0xFF); emit8(0xD0); // call r8
emit8(0x48); emit8(0x83); emit8(0xC4); emit8(0x20); // add rsp, 32
emit8(0x5A); // pop rdx
emit8(0x59); // pop rcx
return;
}
// Dictionary Resolver (Call User Word)
@@ -162,6 +207,7 @@ internal void compile_action(U4 val) {
IA_ void compile_and_run_tape(void) {
farena_reset(&code_arena);
dict_count = 0;
log_count = 0;
// Prologue: Load VM state from globals[14] and [15]
emit8(0x48); emit8(0x8B); emit8(0x41); emit8(0x70); // mov rax, [rcx+112]
@@ -171,7 +217,9 @@ IA_ void compile_and_run_tape(void) {
B4 in_def = false;
U4 def_jmp_offset = 0;
for (U8 i = 0; i <= cursor_idx; i++) {
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]);
@@ -235,6 +283,9 @@ IA_ void compile_and_run_tape(void) {
#define MS_VK_BACK 0x08
#define MS_VK_TAB 0x09
#define MS_VK_SPACE 0x20
#define MS_VK_F5 0x74
#define MS_VK_PRIOR 0x21
#define MS_VK_NEXT 0x22
// --- Window Procedure ---
S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
@@ -251,7 +302,7 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
// Skip control characters in WM_CHAR (handled in KEYDOWN)
if (c < 32) break;
if (tag == tmpl(STag, Data)) {
if (tag == STag_Data) {
// Hex input
U4 digit = 16;
if (c >= '0' && c <= '9') digit = c - '0';
@@ -261,11 +312,24 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
val = ((val << 4) | digit) & 0x0FFFFFFF;
tape_ptr[cursor_idx] = PACK_TOKEN(tag, val);
}
} else {
// 2-Char String input (Shift left and insert new char)
val = ((val << 8) | c) & 0xFFFF;
} else if (tag != STag_Format) {
U8*r anno_ptr = C_(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';
// Update the 2-char token ID from the first 2 chars
char c1 = anno_str[0] ? anno_str[0] : ' ';
char c2 = anno_str[1] ? anno_str[1] : ' ';
val = ID2(c1, c2);
tape_ptr[cursor_idx] = PACK_TOKEN(tag, val);
}
}
vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals));
compile_and_run_tape();
@@ -273,68 +337,118 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
return 0;
}
case MS_WM_KEYDOWN: {
if (wparam == 0x45 && editor_mode == MODE_NAV) { // 'E'
editor_mode = MODE_EDIT;
ms_invalidate_rect(hwnd, NULL, true);
return 0;
}
if (wparam == 0x1B && editor_mode == MODE_EDIT) { // ESC
editor_mode = MODE_NAV;
ms_invalidate_rect(hwnd, NULL, 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 = C_(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';
char c1 = anno_str[0] ? anno_str[0] : ' ';
char c2 = anno_str[1] ? anno_str[1] : ' ';
tape_ptr[cursor_idx] = PACK_TOKEN(tag, ID2(c1, c2));
}
}
vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals));
compile_and_run_tape();
ms_invalidate_rect(hwnd, NULL, true);
}
return 0; // Block navigation keys in Edit Mode
}
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]) != tmpl(STag, Format)) line_start--;
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]) != tmpl(STag, Format)) prev_line_start--;
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]) != tmpl(STag, Format)) line_start--;
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]) != tmpl(STag, Format)) next_line_start++;
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++; // Skip the newline
U8 next_line_end = next_line_start;
while (next_line_end < tape_count && UNPACK_TAG(tape_ptr[next_line_end]) != tmpl(STag, Format)) next_line_end++;
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_TAB) {
// Cycle Color Tag
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) {
// Delete Token and move cursor left
// Delete Token and move cursor left, shifting BOTH arenas
if (tape_count > 0) {
U8*r anno_ptr = C_(U8*r, anno_arena.start);
for (U8 i = cursor_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);
if (cursor_idx > 0) cursor_idx--;
}
} else if (wparam == MS_VK_SPACE || wparam == MS_VK_RETURN) {
// Insert New Token (Pre-append at cursor)
if (tape_arena.used + sizeof(U4) <= tape_arena.capacity) {
// Insert New Token (Pre-append at cursor), shifting BOTH arenas
if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) {
U8*r anno_ptr = C_(U8*r, anno_arena.start);
for (U8 i = tape_count; i > cursor_idx; i--) {
tape_ptr[i] = tape_ptr[i-1];
anno_ptr[i] = anno_ptr[i-1];
}
if (wparam == MS_VK_RETURN) {
tape_ptr[cursor_idx] = PACK_TOKEN(tmpl(STag, Format), 0xA); // Newline
tape_ptr[cursor_idx] = PACK_TOKEN(STag_Format, 0xA); // Newline
anno_ptr[cursor_idx] = 0;
cursor_idx++; // Move past newline
} else {
tape_ptr[cursor_idx] = PACK_TOKEN(tmpl(STag, Comment), ID2(' ',' '));
tape_ptr[cursor_idx] = PACK_TOKEN(STag_Comment, ID2(' ',' '));
anno_ptr[cursor_idx] = 0;
cursor_idx++; // Move past space
}
tape_arena.used += sizeof(U4);
anno_arena.used += sizeof(U8);
}
}
// Interaction: Reset VM and compile up to cursor
// Interaction: Reset VM and compile
vm_rax = 0; vm_rdx = 0;
mem_zero(u8_(vm_globals), sizeof(vm_globals));
@@ -354,6 +468,7 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
S4 x = start_x, y = start_y;
U4*r tape_ptr = C_(U4*r, tape_arena.start);
U8*r anno_ptr = C_(U8*r, anno_arena.start);
// Render Tokens
for (U8 i = 0; i < tape_count; i++) {
@@ -361,19 +476,23 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
x = start_x; y += spacing_y;
}
if (i == cursor_idx) {
void* hBrush = ms_get_stock_object(2); // GRAY_BRUSH
S4 render_y = y - scroll_y_offset;
if (i == cursor_idx && render_y >= 30 && render_y < 500) {
void* hBrush = ms_get_stock_object(editor_mode == MODE_EDIT ? 0 : 2); // WHITE_BRUSH : GRAY_BRUSH
ms_select_object(hdc, hBrush);
ms_rectangle(hdc, x - 5, y - 2, x + 95, y + 22);
ms_rectangle(hdc, x - 5, render_y - 2, x + 95, render_y + 22);
}
if (render_y >= 30 && render_y < 500) {
U4 t = tape_ptr[i];
U4 tag = UNPACK_TAG(t);
U4 val = UNPACK_VAL(t);
U8 anno = anno_ptr[i];
if (tag == tmpl(STag, Format) && val == 0xA) {
if (tag == STag_Format && val == 0xA) {
ms_set_text_color(hdc, 0x00444444);
ms_text_out_a(hdc, x, y, " \\n ", 6);
ms_text_out_a(hdc, x, render_y, " \\n ", 6);
x = start_x;
y += spacing_y;
} else {
@@ -381,32 +500,67 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
const char* prefix = tag_prefixes[tag];
ms_set_text_color(hdc, color);
if (editor_mode == MODE_EDIT && i == cursor_idx) {
ms_set_text_color(hdc, 0x00000000); // Black text on white cursor
}
char val_str[9];
if (tag == tmpl(STag, Data)) {
if (tag == STag_Data) {
u64_to_hex(val, val_str, 6);
val_str[6] = '\0';
} else {
// Decode 2-character dictionary ID
// Extract annotation string
char* a_str = (char*)&anno;
if (a_str[0] == '\0') {
// Fallback to 2-character ID
val_str[0] = (char)((val >> 8) & 0xFF);
val_str[1] = (char)(val & 0xFF);
val_str[2] = ' '; val_str[3] = ' '; val_str[4] = ' '; val_str[5] = ' ';
val_str[6] = '\0';
} else {
mem_copy(u8_(val_str), u8_(a_str), 8);
val_str[8] = '\0';
}
}
char out_buf[10];
char out_buf[12];
out_buf[0] = prefix[0];
out_buf[1] = ' ';
mem_copy(u8_(out_buf + 2), u8_(val_str), 6);
out_buf[8] = '\0';
mem_copy(u8_(out_buf + 2), u8_(val_str), 8);
out_buf[10] = '\0';
ms_text_out_a(hdc, x, y, out_buf, 8);
ms_text_out_a(hdc, x, render_y, out_buf, 10);
x += spacing_x;
}
} else if (UNPACK_TAG(tape_ptr[i]) == STag_Format && UNPACK_VAL(tape_ptr[i]) == 0xA) {
x = start_x;
y += spacing_y;
} else {
x += spacing_x;
}
}
// Draw a solid background behind the HUD to cover scrolling text
void* hBlackBrush = ms_get_stock_object(4); // BLACK_BRUSH
ms_select_object(hdc, hBlackBrush);
ms_rectangle(hdc, 0, 500, 1100, 750);
ms_rectangle(hdc, 0, 0, 1100, 40);
ms_set_text_color(hdc, 0x00AAAAAA);
ms_text_out_a(hdc, 40, 20, "x86-64 Machine Code Emitter | 2-Reg Stack + Global Tape | Factorial", 68);
ms_text_out_a(hdc, 40, 10, "x86-64 Machine Code Emitter | 2-Reg Stack | [F5] Toggle Run Mode | [PgUp/PgDn] Scroll", 85);
// Render VM State
ms_set_text_color(hdc, 0x00FFFFFF);
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);
ms_text_out_a(hdc, 40, 520, jit_str, 41);
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);
ms_set_text_color(hdc, 0x0033FF33);
ms_text_out_a(hdc, 40, 550, state_str, 29);
// HUD: Display Current Token Meaning
if (tape_count > 0 && cursor_idx < tape_count) {
@@ -423,29 +577,27 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
semantics_str[13 + name_len] = '\0';
ms_set_text_color(hdc, cur_color);
ms_text_out_a(hdc, 40, 540, semantics_str, 13 + name_len);
ms_text_out_a(hdc, 40, 580, semantics_str, 13 + name_len);
}
// Render VM State
ms_set_text_color(hdc, 0x00FFFFFF);
char jit_str[32] = "JIT Size: 0x000 bytes";
u64_to_hex(code_arena.used, jit_str + 12, 3);
ms_text_out_a(hdc, 40, 480, jit_str, 21);
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);
ms_set_text_color(hdc, 0x0033FF33);
ms_text_out_a(hdc, 40, 510, state_str, 29);
ms_set_text_color(hdc, 0x00FFFFFF);
ms_text_out_a(hdc, 400, 480, "Global Memory (Contiguous Array):", 33);
ms_text_out_a(hdc, 400, 520, "Global Memory (Contiguous Array):", 33);
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);
ms_set_text_color(hdc, 0x00FFFF33);
ms_text_out_a(hdc, 400, 510 + (i * 25), glob_str, 13);
ms_text_out_a(hdc, 400, 550 + (i * 25), glob_str, 13);
}
// Print Log
ms_set_text_color(hdc, 0x00FFFFFF);
ms_text_out_a(hdc, 750, 520, "Print Log:", 10);
for (int i=0; i<log_count && i<4; i++) {
char log_str[32] = "00000000";
u64_to_hex(log_buffer[i], log_str, 8);
ms_set_text_color(hdc, 0x00FF33FF);
ms_text_out_a(hdc, 750, 550 + (i * 25), log_str, 8);
}
ms_select_object(hdc, hOldFont);
@@ -460,55 +612,62 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
int main(void) {
// 1. Initialize Memory Arenas using WinAPI + FArena
Slice tape_mem = slice_ut_(u8_(ms_virtual_alloc(NULL, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE)), 64 * 1024);
Slice anno_mem = slice_ut_(u8_(ms_virtual_alloc(NULL, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE)), 64 * 1024);
Slice code_mem = slice_ut_(u8_(ms_virtual_alloc(NULL, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_EXECUTE_READWRITE)), 64 * 1024);
if (!tape_mem.ptr || !code_mem.ptr) ms_exit_process(1);
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);
// Bootstrap Robust Sample: Factorial State Machine
scatter(PACK_TOKEN(tmpl(STag, Comment), ID2('I','N'))); // .IN
scatter(PACK_TOKEN(tmpl(STag, Data), 5)); // $5
scatter(PACK_TOKEN(tmpl(STag, Data), 0)); // $0 (Addr)
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('!',' '))); // ^!
scatter(PACK_TOKEN(STag_Comment, ID2('I','N')), "INIT "); // .IN
scatter(PACK_TOKEN(STag_Data, 5), 0); // $5
scatter(PACK_TOKEN(STag_Data, 0), 0); // $0 (Addr)
scatter(PACK_TOKEN(STag_Imm, ID2('!',' ')), "STORE "); // ^!
scatter(PACK_TOKEN(tmpl(STag, Data), 1)); // $1
scatter(PACK_TOKEN(tmpl(STag, Data), 1)); // $1 (Addr)
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('!',' '))); // ^!
scatter(PACK_TOKEN(STag_Data, 1), 0); // $1
scatter(PACK_TOKEN(STag_Data, 1), 0); // $1 (Addr)
scatter(PACK_TOKEN(STag_Imm, ID2('!',' ')), "STORE "); // ^!
scatter(PACK_TOKEN(tmpl(STag, Format), 0xA)); // Newline
scatter(PACK_TOKEN(STag_Format, 0xA), 0); // Newline
// Define the FS (Factorial Step) word in memory
scatter(PACK_TOKEN(tmpl(STag, Define), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Data), 0));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('@',' ')));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('R','0')));
scatter(PACK_TOKEN(tmpl(STag, Format), 0xA)); // Newline
scatter(PACK_TOKEN(STag_Define, ID2('F','S')), "F_STEP ");
scatter(PACK_TOKEN(STag_Data, 0), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Call, ID2('R','0')), "RET_IF_Z");
scatter(PACK_TOKEN(STag_Format, 0xA), 0); // Newline
scatter(PACK_TOKEN(tmpl(STag, Data), 1));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('@',' ')));
scatter(PACK_TOKEN(tmpl(STag, Data), 0));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('@',' ')));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('M','*')));
scatter(PACK_TOKEN(tmpl(STag, Data), 1));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('!',' ')));
scatter(PACK_TOKEN(tmpl(STag, Format), 0xA)); // Newline
scatter(PACK_TOKEN(STag_Data, 1), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Data, 0), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Call, ID2('M','*')), "MULT ");
scatter(PACK_TOKEN(STag_Data, 1), 0);
scatter(PACK_TOKEN(STag_Call, ID2('!',' ')), "STORE ");
scatter(PACK_TOKEN(STag_Format, 0xA), 0); // Newline
scatter(PACK_TOKEN(tmpl(STag, Data), 0));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('@',' ')));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('-','1')));
scatter(PACK_TOKEN(tmpl(STag, Data), 0));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('!',' ')));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('R','E'))); // Return!
scatter(PACK_TOKEN(STag_Data, 0), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Call, ID2('-','1')), "DEC ");
scatter(PACK_TOKEN(STag_Data, 0), 0);
scatter(PACK_TOKEN(STag_Call, ID2('!',' ')), "STORE ");
scatter(PACK_TOKEN(tmpl(STag, Format), 0xA)); // Newline
scatter(PACK_TOKEN(STag_Data, 1), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Call, ID2('P','R')), "PRINT "); // Print Accumulator!
scatter(PACK_TOKEN(STag_Call, ID2('R','E')), "RETURN "); // Return!
scatter(PACK_TOKEN(STag_Format, 0xA), 0); // Newline
// Call it
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S'))); // ^FS
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP "); // ^FS
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP ");
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP ");
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP ");
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP ");
MS_WNDCLASSA wc;
mem_fill(u8_(& wc), 0, sizeof(wc));
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB