Removing recursive xyw_eval calls which could corrupt *pc.
h3rald h3rald@h3rald.com
Mon, 20 Jul 2026 11:23:37 +0200
M
xyw.h
→
xyw.h
@@ -31,6 +31,14 @@ xyw_input input;
xyw_output output; } xyw_device; +typedef struct +{ + xyw_word handler; + int pending; +} xyw_vector_slot; + +void xyw_request_vector(xyw_word handler); + // Main Globals extern xyw_device xyw_devices[XYW_TOTAL_DEVICES]; extern const char xyw_instructions[][4];
M
xywrun.c
→
xywrun.c
@@ -13,6 +13,7 @@
#define USER_STACK_SIZE 128 #define SYSTEM_FRAME_SIZE 8 #define SYSTEM_MAX_FRAMES 48 +#define XYW_MAX_VECTORS 4 #define USER_MEMORY_START 0x000 #define DEVICE_AREA_START 0xff00@@ -85,6 +86,9 @@ static xyw_word yw_storage = 0; // 16-bit Y register storage
xyw_word *pc = &pc_storage; xyw_word *xw = &xw_storage; xyw_word *yw = &yw_storage; + +//// Vector slots +static xyw_vector_slot vector_slots[XYW_MAX_VECTORS]; //// Helpers to retrieve device number and address within the device static inline int get_device(xyw_word addr)@@ -194,6 +198,39 @@ for (int i = 0; i < SYSTEM_FRAME_SIZE; i++) base[i] = 0;
return return_addr; } +//// Vector dispatch (deferred, non-recursive event handling) + +// Request a vector +void xyw_request_vector(xyw_word handler) +{ + for (int i = 0; i < XYW_MAX_VECTORS; i++) + { + if (!vector_slots[i].pending) + { + vector_slots[i].handler = handler; + vector_slots[i].pending = 1; + return; + } + } + XYW_DBG("Vector table full, dropping request for handler %04X\n", handler); +} + +// Dispatch requested vectors (called once per xyw_eval iteration) +static void dispatch_vectors(void) +{ + for (int i = 0; i < XYW_MAX_VECTORS; i++) + { + if (vector_slots[i].pending) + { + vector_slots[i].pending = 0; + XYW_DBG("Dispatching vector to handler %04X\n", vector_slots[i].handler); + ss_push_frame(*pc); + *pc = vector_slots[i].handler - 1; + return; + } + } +} + //// User stack management static void us_push(xyw_byte val)@@ -388,32 +425,15 @@ if (on_timer_handler != 0)
{ if (readb(CLOCK_ON_TIMER_ELAPSED)) { - XYW_DBG("Timer elapsed, jumping to handler at %04X\n", on_timer_handler); - xyw_eval(on_timer_handler); + XYW_DBG("Timer elapsed, requesting vector for handler at %04X\n", on_timer_handler); + xyw_request_vector(on_timer_handler); } } - // Process terminal arguments if not already done - static int argument_processing_active = 0; - if (!xyw_argv_processed && !argument_processing_active && XYW_PEEKW(&xyw_memory[TERMINAL_ON_ARGUMENT]) && !(system_error_state())) - { - argument_processing_active = 1; // Prevent re-entry - for (int i = 1; i < xyw_argc; i++) - { - XYW_DBG("Processing argument %d of %d: %s\n", i, xyw_argc, xyw_argv[i]); - const char *arg = xyw_argv[i]; - for (size_t j = 0; arg[j] != '\0'; j++) - { - writeb(TERMINAL_INPUT, (xyw_byte)arg[j]); - } - if (i < xyw_argc - 1) - { - writeb(TERMINAL_INPUT, XYW_ARGUMENT_SEPARATOR); - } - } - writeb(TERMINAL_INPUT, XYW_END_OF_ARGUMENTS); - xyw_argv_processed = 1; - argument_processing_active = 0; - } + + // TODO: Beeper playback-finished handling (need BEEPER_ON_FINISHED vector) + // xyw_word on_beeper_finished = XYW_PEEKW(&xyw_memory[BEEPER_ON_FINISHED]); + // if (on_beeper_finished != 0 && beeper_check_finished()) + // xyw_request_vector(on_beeper_finished); return 0; }@@ -436,6 +456,7 @@ }
while ((system_running_state()) && *pc < DEVICE_AREA_START) { process_events(); + dispatch_vectors(); XYW_DBG(" -- PC: %04X -> %02X (%s) [U:%02X|S:%02X|X:%02X|Y:%02X|XW:%04X|YW:%04X]\n", *pc, xyw_memory[*pc], xyw_instructions[xyw_memory[*pc] & 0x1F], u, s, *x, *y, *xw, *yw); switch (xyw_memory[*pc]) {@@ -537,6 +558,26 @@
int eval_result = xyw_eval(0x0000); if (!eval_result) { + // Handle command line arguments + if (!xyw_argv_processed && !(system_error_state()) && XYW_PEEKW(&xyw_memory[TERMINAL_ON_ARGUMENT])) + { + for (int i = 1; i < xyw_argc; i++) + { + XYW_DBG("Processing argument %d of %d: %s\n", i, xyw_argc, xyw_argv[i]); + const char *arg = xyw_argv[i]; + for (size_t j = 0; arg[j] != '\0'; j++) + { + writeb(TERMINAL_INPUT, (xyw_byte)arg[j]); + } + if (i < xyw_argc - 1) + { + writeb(TERMINAL_INPUT, XYW_ARGUMENT_SEPARATOR); + } + } + writeb(TERMINAL_INPUT, XYW_END_OF_ARGUMENTS); + xyw_argv_processed = 1; + } + // Check if we need to enter an event loop (keypress handler or timer) xyw_word on_keypress_handler = XYW_PEEKW(&xyw_memory[TERMINAL_ON_KEYPRESS]); xyw_word on_timer_handler = XYW_PEEKW(&xyw_memory[CLOCK_ON_TIMER_ELAPSED]);