diff --git a/include/SASM/sasm_instructions.h b/include/SASM/sasm_instructions.h index 2ccfef8a..0de7f3df 100644 --- a/include/SASM/sasm_instructions.h +++ b/include/SASM/sasm_instructions.h @@ -1,16 +1,33 @@ #include "univ_defs.h" +/** + * Meta flags for CPU state. F1-F7 are reserved for user-defined conditions. + * Users can assign custom meanings to these flags at runtime or via configuration. + * Example usage: + * setFlag(META_F1, cpu, true); // Set user-defined flag 1 + * getFlag(META_F1, cpu); // Check user-defined flag 1 + */ typedef enum { - META_HALT = 1 << 0, - META_F1 = 1 << 1, - META_F2 = 1 << 2, - META_F3 = 1 << 3, - META_F4 = 1 << 4, - META_F5 = 1 << 5, - META_F6 = 1 << 6, - META_F7 = 1 << 7 + META_HALT = 1 << 0, // System Halt + META_F1 = 1 << 1, // User-defined Flag 1 + META_F2 = 1 << 2, // User-defined Flag 2 + META_F3 = 1 << 3, // User-defined Flag 3 + META_F4 = 1 << 4, // User-defined Flag 4 + META_F5 = 1 << 5, // User-defined Flag 5 + META_F6 = 1 << 6, // User-defined Flag 6 + META_F7 = 1 << 7 // User-defined Flag 7 } Meta; +/** + * To assign a meaning to a user-defined flag, set up a mapping in your configuration or code: + * Example: + * // In your config or code + * #define USER_FLAG_CONDITION_1 "Interrupt Enabled" + * #define USER_FLAG_CONDITION_2 "Debug Mode" + * // ... + * Then use setFlag/getFlag to manipulate these flags as needed. + */ + typedef enum { INST_DONOP = 0, @@ -189,3 +206,55 @@ OpcodeDetails getOpcodeDetails(Opcode type); void setFlag(Meta f, CPU* cpu, bool state); bool getFlag(Meta f, const CPU* cpu); + +#include + +#define USER_FLAG_COUNT 7 + +// Structure for user-defined flag metadata +typedef struct { + const char* name; // Human-readable name or meaning + int (*condition_cb)(const struct CPU* cpu); // Optional callback for dynamic condition +} UserFlagDef; + +// Registry for user-defined flags (F1-F7) +extern UserFlagDef user_flag_registry[USER_FLAG_COUNT]; + +// Register a user-defined flag (index 0-6 for F1-F7) +void register_user_flag(int flag_index, const char* name, int (*condition_cb)(const struct CPU*)); + +// Get user-defined flag name +const char* get_user_flag_name(int flag_index); + +// Evaluate user-defined flag condition (returns 0 if no callback) +int eval_user_flag_condition(int flag_index, const struct CPU* cpu); + +/** + * === User-Defined Flag System === + * + * This system allows you to assign semantic meaning and dynamic logic to each user flag (F1-F7). + * + * Example: Registering a flag for "Interrupt Enabled" with a dynamic condition. + * + * int interrupt_enabled_cb(const struct CPU* cpu) { + * // Custom logic: e.g., check a register or memory-mapped IO + * return (cpu->registers.I0 & 0x1) != 0; + * } + * register_user_flag(0, "Interrupt Enabled", interrupt_enabled_cb); + * + * // Query the flag's state (dynamic or static) + * if (getFlag(META_F1, cpu) || eval_user_flag_condition(0, cpu)) { + * // ... handle interrupt logic ... + * } + * + * You can use the provided macros for clarity: + * #define META_USER(n) (1 << ((n)+1)) // n in 0..6 for F1..F7 + * #define USER_FLAG_INDEX(meta_flag) (__builtin_ctz(meta_flag) - 1) + * + * // Example usage: + * setFlag(META_USER(2), cpu, true); // Set F3 + * int idx = USER_FLAG_INDEX(META_F3); // idx == 2 + * const char* name = get_user_flag_name(idx); + * + * This pattern enables scalable, readable, and powerful user-driven flag logic. + */ \ No newline at end of file diff --git a/include/VM/virex_ui.h b/include/VM/virex_ui.h index ace32aed..97c00633 100644 --- a/include/VM/virex_ui.h +++ b/include/VM/virex_ui.h @@ -26,30 +26,48 @@ enum Inputs MAX_INPUTS }; -void OnInstructionExecution(Vm *vm, size_t instructionIndex, bool debug); - -void OnStart(); - -void OnPause(); - -void OnExit(); - -int getUserInput(); - -void printOut(int id, const char *str, ...); - -void printOutWithColor(int id, int colorPair, const char *str, ...); - -void clearWindow(int id); - -void moveCursorWithinWindow(int id, int y, int x); - -char getChar(int id); - -void refreshAllWindows(); - -void readFilePath(int id, const char *msg, const char **filePath); - -void InputMenu(int *highlight, int *ch); +// UI Interface abstraction for modularity and future GUI support +/** + * UI_Interface: Abstract interface for all UI implementations (CLI, TUI, GUI, etc). + * + * To add a new UI (such as a GUI), simply implement all functions in this struct for your UI, + * and set the global UI pointer to your implementation (e.g., UI = &GUI_UI;). + * This enables seamless switching between CLI, TUI, and future GUI modes. + */ +typedef struct UI_Interface { + void (*OnInstructionExecution)(Vm *vm, size_t instructionIndex, bool debug); + void (*OnStart)(); + void (*OnPause)(); + void (*OnExit)(); + int (*getUserInput)(); + void (*printOut)(int id, const char *str, ...); + void (*printOutWithColor)(int id, int colorPair, const char *str, ...); + void (*clearWindow)(int id); + void (*moveCursorWithinWindow)(int id, int y, int x); + char (*getChar)(int id); + void (*refreshAllWindows)(); + void (*readFilePath)(int id, const char *msg, const char **filePath); + void (*InputMenu)(int *highlight, int *ch); + void (*SetInputEnable)(bool enable); +}; -void SetInputEnable(bool enable); \ No newline at end of file +// Externally accessible UI interface pointer +extern struct UI_Interface *UI; + +// Default CLI/TUI implementations (to be defined in respective source files) +void CLI_OnInstructionExecution(Vm *vm, size_t instructionIndex, bool debug); +void CLI_OnStart(); +void CLI_OnPause(); +void CLI_OnExit(); +int CLI_getUserInput(); +void CLI_printOut(int id, const char *str, ...); +void CLI_printOutWithColor(int id, int colorPair, const char *str, ...); +void CLI_clearWindow(int id); +void CLI_moveCursorWithinWindow(int id, int y, int x); +char CLI_getChar(int id); +void CLI_refreshAllWindows(); +void CLI_readFilePath(int id, const char *msg, const char **filePath); +void CLI_InputMenu(int *highlight, int *ch); +void CLI_SetInputEnable(bool enable); + +// Add similar declarations for TUI/GUI as needed \ No newline at end of file diff --git a/src/SASM/sasm_instructions.c b/src/SASM/sasm_instructions.c index 8d9eddc5..dc2ec1f5 100644 --- a/src/SASM/sasm_instructions.c +++ b/src/SASM/sasm_instructions.c @@ -130,3 +130,40 @@ inline bool getFlag(Meta f, const CPU* cpu) { return cpu->flags & f; } + +UserFlagDef user_flag_registry[USER_FLAG_COUNT] = {0}; + +void register_user_flag(int flag_index, const char* name, int (*condition_cb)(const CPU*)) { + if (flag_index < 0 || flag_index >= USER_FLAG_COUNT) return; + user_flag_registry[flag_index].name = name; + user_flag_registry[flag_index].condition_cb = condition_cb; +} + +const char* get_user_flag_name(int flag_index) { + if (flag_index < 0 || flag_index >= USER_FLAG_COUNT) return NULL; + return user_flag_registry[flag_index].name; +} + +int eval_user_flag_condition(int flag_index, const CPU* cpu) { + if (flag_index < 0 || flag_index >= USER_FLAG_COUNT) return 0; + if (user_flag_registry[flag_index].condition_cb) + return user_flag_registry[flag_index].condition_cb(cpu); + return 0; +} + +// Example: Register a user-defined flag for "Interrupt Enabled" and use it in logic +static int interrupt_enabled_cb(const CPU* cpu) { + return (cpu->registers.I0 & 0x1) != 0; +} + +void setup_user_flags(CPU* cpu) { + register_user_flag(0, "Interrupt Enabled", interrupt_enabled_cb); + setFlag(META_F1, cpu, false); // Start with interrupt disabled +} + +void handle_interrupt(CPU* cpu) { + if (getFlag(META_F1, cpu) || eval_user_flag_condition(0, cpu)) { + // Interrupt logic here + setFlag(META_F1, cpu, false); // Clear after handling + } +} \ No newline at end of file diff --git a/src/VM/virex_ui.c b/src/VM/virex_ui.c index 75114037..0bdb04a8 100644 --- a/src/VM/virex_ui.c +++ b/src/VM/virex_ui.c @@ -457,4 +457,42 @@ void InputMenu(int *highlight, int *ch) default: break; } +} + +// CLI implementation wrappers for UI_Interface +void CLI_OnInstructionExecution(Vm *vm, size_t instructionIndex, bool debug) { OnInstructionExecution(vm, instructionIndex, debug); } +void CLI_OnStart() { OnStart(); } +void CLI_OnPause() { OnPause(); } +void CLI_OnExit() { OnExit(); } +int CLI_getUserInput() { return getUserInput(); } +void CLI_printOut(int id, const char *str, ...) { va_list args; va_start(args, str); printOut(id, str, args); va_end(args); } +void CLI_printOutWithColor(int id, int colorPair, const char *str, ...) { va_list args; va_start(args, str); printOutWithColor(id, colorPair, str, args); va_end(args); } +void CLI_clearWindow(int id) { clearWindow(id); } +void CLI_moveCursorWithinWindow(int id, int y, int x) { moveCursorWithinWindow(id, y, x); } +char CLI_getChar(int id) { return getChar(id); } +void CLI_refreshAllWindows() { refreshAllWindows(); } +void CLI_readFilePath(int id, const char *msg, const char **filePath) { readFilePath(id, msg, filePath); } +void CLI_InputMenu(int *highlight, int *ch) { InputMenu(highlight, ch); } +void CLI_SetInputEnable(bool enable) { SetInputEnable(enable); } + +// UI_Interface instance for CLI +struct UI_Interface CLI_UI = { + .OnInstructionExecution = CLI_OnInstructionExecution, + .OnStart = CLI_OnStart, + .OnPause = CLI_OnPause, + .OnExit = CLI_OnExit, + .getUserInput = CLI_getUserInput, + .printOut = CLI_printOut, + .printOutWithColor = CLI_printOutWithColor, + .clearWindow = CLI_clearWindow, + .moveCursorWithinWindow = CLI_moveCursorWithinWindow, + .getChar = CLI_getChar, + .refreshAllWindows = CLI_refreshAllWindows, + .readFilePath = CLI_readFilePath, + .InputMenu = CLI_InputMenu, + .SetInputEnable = CLI_SetInputEnable +}; + +// Global pointer to active UI +struct UI_Interface *UI = &CLI_UI; } \ No newline at end of file